feat: Enhance security by adding user permissions in Dockerfile, parameterized queries in pronunciation_store, and secure filename handling in routes

This commit is contained in:
JB
2025-11-28 13:19:53 -08:00
parent 39628453de
commit ad70c630c7
6 changed files with 34 additions and 3 deletions
+6 -1
View File
@@ -52,6 +52,11 @@ ENV ABOGEN_UPLOAD_ROOT=/data/uploads \
HF_HOME=/data/huggingface \
HUGGINGFACE_HUB_CACHE=/data/huggingface/hub
RUN mkdir -p /data/uploads /data/outputs /data/cache /data/voice-cache /data/huggingface
# Create non-root user and setup permissions
RUN useradd -m -u 1000 abogen \
&& mkdir -p /data/uploads /data/outputs /data/cache /data/voice-cache /data/huggingface \
&& chown -R abogen:abogen /data /app
USER abogen
CMD ["abogen"]
+1
View File
@@ -86,6 +86,7 @@ def load_overrides(language: str, tokens: Iterable[str]) -> Dict[str, Dict[str,
normalized_tokens = {normalize_token(token) for token in tokens if token}
if not normalized_tokens:
return {}
# Use parameterized queries to prevent SQL injection
placeholders = ",".join("?" for _ in normalized_tokens)
with _DB_LOCK:
conn = _connect()
+3
View File
@@ -327,6 +327,9 @@ def create_process(cmd, stdin=None, text=True, capture_output=False):
# Determine shell usage: use shell only for string commands
use_shell = isinstance(cmd, str)
if use_shell:
logger.warning("Security Warning: create_process called with string command. Prefer using a list of arguments to avoid shell injection risks.")
kwargs = {
"shell": use_shell,
"stdout": subprocess.PIPE,
+22 -2
View File
@@ -8,7 +8,7 @@ from typing import Any, Optional
from flask import Flask
from abogen.utils import get_user_cache_path, get_user_output_path
from abogen.utils import get_user_cache_path, get_user_output_path, get_user_settings_dir
from .conversion_runner import run_conversion_job
from .service import build_service
@@ -50,6 +50,26 @@ def _default_dirs() -> tuple[Path, Path]:
return uploads, outputs
def _get_secret_key() -> str:
env_key = os.environ.get("ABOGEN_SECRET_KEY")
if env_key:
return env_key
try:
settings_dir = Path(get_user_settings_dir())
settings_dir.mkdir(parents=True, exist_ok=True)
secret_file = settings_dir / ".secret_key"
if secret_file.exists():
return secret_file.read_text(encoding="utf-8").strip()
key = os.urandom(24).hex()
secret_file.write_text(key, encoding="utf-8")
return key
except Exception:
# Fallback if we can't write to settings dir
return os.urandom(24).hex()
def create_app(config: Optional[dict[str, Any]] = None) -> Flask:
uploads_dir, outputs_dir = _default_dirs()
@@ -59,7 +79,7 @@ def create_app(config: Optional[dict[str, Any]] = None) -> Flask:
template_folder="templates",
)
base_config = {
"SECRET_KEY": os.environ.get("ABOGEN_SECRET_KEY", os.urandom(16)),
"SECRET_KEY": _get_secret_key(),
"UPLOAD_FOLDER": str(uploads_dir),
"OUTPUT_FOLDER": str(outputs_dir),
"MAX_CONTENT_LENGTH": 1024 * 1024 * 400, # 400 MB uploads
+1
View File
@@ -4511,6 +4511,7 @@ def enqueue_job() -> ResponseReturnValue:
original_name: str
if file and file.filename:
# secure_filename prevents path traversal attacks
filename = secure_filename(file.filename)
if not filename:
return redirect(url_for("web.index"))