feat(api): emit security response headers on every response (PMS-388) #367
Loading…
Reference in a new issue
No description provided.
Delete branch "feat/PMS-388-app-level-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?
Three of the four browser-facing surfaces shipped with no security response headers; only bunyip-api set a full set. The 2026-06-17 standup rejected the shared Traefik
headers-security@dockermiddleware (broad blast radius: an attempt broke Mokosh and knocked out Bunyip until manual recovery) and moved the fix to the application layer.This is the mokosh-server half: a global
security_headersmiddleware (parity with bunyip-api's.wrap(SecurityHeaders)) layered on the outermost router so it covers the API, the portal API, and thenot_a_frontendfallback uniformly. It sets HSTS (max-age=31536000; includeSubDomains; preload), X-Content-Type-Options: nosniff, X-Frame-Options: DENY, Referrer-Policy: no-referrer, a deny-by-default Permissions-Policy, and a CSP tuned for this surface (default-src 'none' with style-src 'unsafe-inline' so the inline-styled fallback page renders, plus frame-ancestors 'none', base-uri 'none', form-action 'none').The module is gated behind the
serverfeature since it depends on axum. Unit tests assert the full header set and the HSTS/frame-deny/nosniff values are present on a response.#PMS-388