from flask import Flask, request CONTENT_SECURITY_POLICY = "; ".join( ( "default-src 'self'", "script-src 'self'", "style-src 'self'", "img-src 'self' data:", "font-src 'self'", "connect-src 'self'", "object-src 'none'", "base-uri 'self'", "form-action 'self'", "frame-ancestors 'none'", ) ) def configure_security_headers(app: Flask) -> None: @app.after_request def add_security_headers(response): response.headers.setdefault("Content-Security-Policy", CONTENT_SECURITY_POLICY) response.headers.setdefault("X-Content-Type-Options", "nosniff") response.headers.setdefault("X-Frame-Options", "DENY") response.headers.setdefault("Referrer-Policy", "strict-origin-when-cross-origin") response.headers.setdefault( "Permissions-Policy", "camera=(), geolocation=(), microphone=()", ) response.headers.setdefault("Cross-Origin-Opener-Policy", "same-origin") response.headers.setdefault("Cross-Origin-Resource-Policy", "same-origin") if request.endpoint == "static": response.headers["Cache-Control"] = "public, max-age=3600" else: response.headers["Cache-Control"] = "no-store" if app.config["ENABLE_HSTS"] and request.is_secure: response.headers.setdefault( "Strict-Transport-Security", "max-age=31536000; includeSubDomains", ) return response