feat(security): add security response headers [operator-action] (LC-504) #471
Loading…
Reference in a new issue
No description provided.
Delete branch "feat/LC-504-security-headers"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
lets-chat previously returned no transport/framing/sniffing/policy headers on any response; only the session cookie was hardened. This adds a
set_security_headerstower middleware applied as the OUTERMOST layer ofbuild_router, so every response shape (HTML pages, HTMX fragments, the JSON API, webhooks, feeds, static assets, redirects and error responses) carries all six headers.The values are tuned to the existing HTMX/Askama app rather than a from-scratch lockdown, so they cannot break shipped functionality: the CSP keeps
'unsafe-inline'/'unsafe-eval'for the inline<script>blocks and htmxhx-on::*handlers, allowsdata:/blob:plus the Tenor CDN inimg-srcfor avatar/upload previews and the LC-488 GIF picker grid, and allowsws:/wss:inconnect-srcfor the live hub; the real hardening wins areframe-ancestors 'none',object-src 'none',base-uri 'self'andform-action 'self'. Permissions-Policy keeps camera/microphone/display-capture for the WebRTC call surface and denies geolocation and the rest. The middleware only inserts a header the handler did not already set, so a future route can override.A new
server/tests/security_headers.rsasserts all six headers are present on a public 200, an authed page and a redirect, and pins the X-Frame-Options/nosniff/CSP/Permissions-Policy values.Operator-Action: lets-chat now emits HSTS (max-age=31536000; includeSubDomains; preload), Content-Security-Policy, X-Frame-Options DENY, X-Content-Type-Options nosniff, Referrer-Policy and Permissions-Policy on every response; if you terminate TLS at a fronting proxy that also injects these headers reconcile them to avoid duplicates, and be aware the HSTS includeSubDomains/preload directive now applies to the whole domain for a year.
#LC-504