44 lines
1.5 KiB
Python
44 lines
1.5 KiB
Python
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
|