"""Opt-in reverse-proxy mode. Default OFF. When off this is a strict no-op: the Flask app is left exactly as it was, ``X-Forwarded-*`` headers are NOT trusted (so a direct client can't spoof its IP/scheme), and the session cookie keeps Flask's defaults. So a normal direct / LAN install is byte-for-byte unchanged. Only when the operator explicitly sets ``security.trust_reverse_proxy: true`` — they're running behind nginx / Caddy / Traefik that terminates TLS — do we: - trust the proxy's ``X-Forwarded-For/Proto/Host/Port`` (correct client IP, HTTPS detection, redirects), and - mark the session cookie ``Secure`` (HTTPS-only) + ``SameSite=Lax``. Gated this way the security/UX change is scoped strictly to people who turned it on; everyone else is untouched. """ from __future__ import annotations CONFIG_KEY = "security.trust_reverse_proxy" def apply_reverse_proxy_mode(app, config_get) -> bool: """Apply reverse-proxy hardening to ``app`` iff the operator enabled it. ``config_get`` is a ``config_manager.get``-style callable ``(key, default)``. Returns True if proxy mode was enabled, False (no-op) otherwise. Never raises out — a failure to enable falls back to the safe no-op behaviour. """ try: if not config_get(CONFIG_KEY, False): return False from werkzeug.middleware.proxy_fix import ProxyFix # Trust exactly one proxy hop for each forwarded header. app.wsgi_app = ProxyFix(app.wsgi_app, x_for=1, x_proto=1, x_host=1, x_port=1) app.config["SESSION_COOKIE_SECURE"] = True app.config["SESSION_COOKIE_SAMESITE"] = "Lax" return True except Exception: # If anything goes wrong, behave like off — never break startup over this. return False __all__ = ["apply_reverse_proxy_mode", "CONFIG_KEY"]