"""Session-based CSRF token: generate per-session, double-submit on POST.""" import secrets from flask import abort, request, session # Endpoint paths exempt from CSRF (machine-to-machine POSTs from PXE clients # that have no browser session to carry a token). Air-gapped LAN; treated as # trust-by-network. Keep the list short and explicit. CSRF_EXEMPT_PATHS = { "/imaging/status", } def generate_csrf_token(): """Return the CSRF token for the current session, creating one if needed.""" if "_csrf_token" not in session: session["_csrf_token"] = secrets.token_hex(32) return session["_csrf_token"] def init_csrf(app): """Wire CSRF protection into a Flask app: validator + template helper.""" @app.before_request def _validate_csrf(): if request.method != "POST": return if request.path in CSRF_EXEMPT_PATHS: return token = request.form.get("_csrf_token") or request.headers.get("X-CSRF-Token") if not token or token != generate_csrf_token(): abort(403) @app.context_processor def _inject_csrf_token(): return {"csrf_token": generate_csrf_token}