Skip to content

security: add proxy with nonce CSP and cookie gate; static headers (PR 1.2) - #10

Merged
Jeston10 merged 1 commit into
milestone/p1-securityfrom
security/headers-proxy
Sep 16, 2026
Merged

Jeston10 merged 1 commit into
milestone/p1-securityfrom
security/headers-proxy

Conversation

@Jeston10

Copy link
Copy Markdown
Owner

Summary

PR 1.2 of docs/MILESTONES.md (Phase 1). Implements SECURITY §2.9 (HTTP hardening) and the cookie-presence gate from §2.1, using Next 16's proxy.ts (read from the bundled docs before writing).

  • server/security/headers.ts — pure CSP builder (per-request nonce + 'strict-dynamic' for scripts, explicit per-vendor connect-src, no eval in production) and the static header set; unit-tested. CSP_MODE = "report-only" to start (R9).
  • proxy.ts — nonce generation, CSP on request + response (so Next attaches the nonce to its own scripts), redirect to /sign-in when the session cookie is absent on non-public paths (defence in depth; requireUser/getCurrentUser remain the verified gate)
  • next.config.ts — HSTS, nosniff, X-Frame-Options, Referrer-Policy, Permissions-Policy on every response incl. API routes. Server Actions keep Next's default same-origin check (allowedOrigins deliberately unset — it only widens; docs corrected)

Report-only review (R9 procedure)

Loaded /sign-in and /sign-up in a real browser and read every CSP report:

  • Inline styles — React style={} attributes; a nonce in style-src makes browsers ignore 'unsafe-inline', so the policy is style-src 'self' 'unsafe-inline' with scripts nonce-only (rationale in code)
  • unsafe-eval — @firebase/util's new Function("return this") global probe, try/catch-guarded with a fallback → eval stays blocked
  • upgrade-insecure-requests is ignored in report-only mode → emitted only when enforcing

Flip to enforce in its own PR after P1.6 (Sentry CSP reporting gives visibility on authenticated pages); re-review at P2.6 (R2 domain) and P5.3 (Gemini Live WebSocket).

Type

  • security

Verification

  • pnpm lint ✔ · typecheck ✔ · knip ✔ · vitest 24/24 · next build ✔ (proxy registered)
  • Playwright 15/15 on a production build, incl. new assertions: static headers on pages and API routes; CSP present with a nonce; the same nonce appears on Next's <script nonce> tags
  • curl -D - on /sign-in shows the exact served policy

Server checklist

  • No process.env outside config/env.ts (proxy reads env.NODE_ENV)
  • Headers tested (unit + e2e)

Risk watch-list

  • Rows checked: R9 (status updated to In progress: report-only shipped, review done, enforce deferred to a follow-up PR)

Docs

  • docs/SECURITY.md §2.9 rewritten to match the implemented policy; docs/RISKS.md R9

🤖 Generated with Claude Code

PR 1.2 of docs/MILESTONES.md (SECURITY §2.9, §2.1).

- server/security/headers.ts: pure CSP builder (nonce + strict-dynamic
  for scripts, explicit per-vendor connect-src, no eval in production)
  and the static header set; unit-tested. CSP_MODE starts report-only
  (RISKS R9).
- proxy.ts (Next 16 name for middleware): per-request nonce, CSP on
  request + response so Next attaches the nonce to its scripts, and a
  cookie-presence redirect for non-public paths (defence in depth; the
  verified gate stays getCurrentUser/requireUser).
- next.config.ts: HSTS, nosniff, X-Frame-Options, Referrer-Policy,
  Permissions-Policy on every response. Server Actions keep Next's
  default same-origin check; allowedOrigins deliberately unset.
- Report-only review in a real browser: inline-style violations came
  from React style attributes (style-src changed to 'self'
  'unsafe-inline'; scripts stay nonce-only); one eval report is
  @firebase/util's guarded global probe, so eval stays blocked;
  upgrade-insecure-requests is emitted only when enforcing.
- e2e asserts the headers on pages and API routes and that the nonce
  appears on Next's script tags.

Verified: pnpm lint, typecheck, knip, vitest 24/24, next build,
Playwright 15/15 on a production build; curl shows the served policy.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Copilot AI lite review requested due to automatic review settings September 16, 2026 03:58
@vercel

vercel Bot commented Sep 16, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
just-prep-ai-interview-z3cv Error Error Sep 16, 2026 3:59am UTC

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@Jeston10
Jeston10 merged commit 1b069e2 into milestone/p1-security Sep 16, 2026
6 of 7 checks passed
@Jeston10
Jeston10 deleted the security/headers-proxy branch September 16, 2026 04:30

This branch had an error being deployed

1 failed deployment
Preview — f1da37a8 Deployed Sep 16, 2026 by vercel[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants