HTTP Security Headers Hardening
# 🔒 HTTP Security Headers Hardening ## Context OpenScrut currently does not set any security-related HTTP response headers. Modern web applications should include headers that mitigate common attack vectors (clickjacking, MIME-type sniffing, XSS, data leaks via `Referer`, etc.). Adding these headers is a low-effort, high-impact security improvement. Related: OWASP Secure Headers Project — https://owasp.org/www-project-secure-headers/ ## Requirements - Add a Next.js middleware (`src/middleware.ts`) or use `next.config.ts` `headers()` to inject security headers on every response. - Headers to set: - `Strict-Transport-Security: max-age=63072000; includeSubDomains; preload` (HSTS — HTTPS enforcement) - `X-Content-Type-Options: nosniff` (prevent MIME-type sniffing) - `X-Frame-Options: DENY` (clickjacking protection, complement to CSP `frame-ancestors`) - `Referrer-Policy: strict-origin-when-cross-origin` (limit referrer leakage) - `Permissions-Policy: camera=(), microphone=(), geolocation=()` (disable unused browser features) - `Content-Security-Policy` — start with a restrictive policy and loosen only as needed. At minimum: `default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data: blob:; font-src 'self'; connect-src 'self'; frame-ancestors 'none'` - `X-DNS-Prefetch-Control: off` - `X-Permitted-Cross-Domain-Policies: none` - CSP must be compatible with the existing Service Worker (`sw.ts`) and any inline styles used by shadcn/ui or Tailwind. - HSTS must only be sent when the app is served over HTTPS (respect `NODE_ENV` or a dedicated env var). - Headers must not break the PWA manifest or offline fallback. ## Privacy No additional personal data collected. `Referrer-Policy` actually *reduces* data leakage. ## Acceptance Criteria - [ ] Security headers are present on all responses (verified via `curl -I` and browser DevTools). - [ ] CSP does not break any existing page (dashboard, admin, assessor views, offline fallback). - [ ] HSTS is only sent over HTTPS / in production. - [ ] Integration test in `tests/api/` asserts expected headers on a sample route. - [ ] E2E smoke test confirms the app still works end-to-end with headers active. - [ ] Verified in both light and dark mode. - [ ] Documentation updated if any env var is added (e.g., `CSP_REPORT_URI`).
issue