Skip to content

Set Security Headers on All Responses #454

Description

@b-at-neu

Problem

The app sets no security headers on any response. next.config.ts defines no headers() block, vercel.json contains only a buildCommand, and proxy.ts sets x-current-path on the request headers only — nothing writes response headers.

Missing across every route:

Header Consequence of absence
Content-Security-Policy No defense-in-depth under the XSS surface. The surface is clean today (no dangerouslySetInnerHTML, no any), but nothing constrains a future regression.
Strict-Transport-Security No HSTS; first-request downgrade remains possible.
X-Frame-Options / CSP frame-ancestors /applications, /applications/[id], /users, /global-questions and /positions/[id]/edit are all framable — clickjacking against admin and reviewer controls (status changes, bulk updates, admin promotion, question deletion).
X-Content-Type-Options: nosniff Relevant because downloadQuestionFileAnswer serves applicant-uploaded PDF/PNG/JPG bytes back to reviewers.
Referrer-Policy Full paths including /applications/[id] leak to third-party origins via outbound links.

The app is authenticated, stores applicant PII, and is publicly launched as of 2026-08-16.

Acceptance criteria

  • A headers() block in next.config.ts applying to all routes
  • Strict-Transport-Security, X-Content-Type-Options: nosniff, Referrer-Policy, and a frame-ancestors denial are set
  • A CSP is defined, verified against the Neon Auth redirect flow, Vercel Blob download responses, and the next-themes inline script
  • Headers confirmed on a preview deployment before merge

Notes

  • Split the work by risk. The four non-CSP headers are inert and can ship immediately. CSP is the one that can break things: next-themes injects an inline script (needs a nonce or hash) and Neon Auth redirects to an external origin. Suggest landing CSP as Content-Security-Policy-Report-Only first and promoting it once clean.
  • next.config.ts is the right home, not proxy.ts. The proxy matcher deliberately excludes static assets, /429, and prefetch requests, so headers set there would be applied inconsistently.
  • No schema change, no migration, no new dependency.

Found in the 2026-08-16 pre-launch review of main @ 7299ffb. Not part of the 2026-08-10 full platform audit backlog (#401), which scoped permissions, business logic, design, links, DRY, history, workflows and build/CI — but not runtime hardening.

Metadata

Metadata

Assignees

Labels

enhancementNew feature or request

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions