""" utils/security.py — Security headers and upload hardening. """ import re import secrets import unicodedata _FILENAME_SAFE = re.compile(r"[^A-Za-z0-9._-]") def secure_upload_name(filename: str) -> str: """ Normalize a user-supplied filename to a safe ASCII name with a random prefix (prevents traversal, collisions, and overwrites). """ filename = unicodedata.normalize("NFKD", filename or "file") filename = filename.rsplit("/", 1)[-1].rsplit("\\", 1)[-1] filename = _FILENAME_SAFE.sub("_", filename).strip("._") or "file" return f"{secrets.token_hex(8)}_{filename[:120]}" def apply_security_headers(response): """Defensive HTTP headers applied to every response by app.py.""" response.headers.setdefault("X-Content-Type-Options", "nosniff") response.headers.setdefault("X-Frame-Options", "SAMEORIGIN") response.headers.setdefault("Referrer-Policy", "strict-origin-when-cross-origin") response.headers.setdefault( "Permissions-Policy", "camera=(self), geolocation=(self), microphone=(self)" ) return response