Skip to content

security: add Content-Security-Policy header (audit O5)#64

Merged
projectamazonph merged 1 commit into
mainfrom
claude/remaining-todos-muoxgh
Jul 20, 2026
Merged

security: add Content-Security-Policy header (audit O5)#64
projectamazonph merged 1 commit into
mainfrom
claude/remaining-todos-muoxgh

Conversation

@projectamazonph

@projectamazonph projectamazonph commented Jul 20, 2026

Copy link
Copy Markdown
Owner

Summary

  • CSP header deferred since Sprint 12 (audit finding O5 in docs/security/code-audit-2026-07-15.md).
  • Ships in Report-Only mode by default (Content-Security-Policy-Report-Only) so it can never break the live site — browsers evaluate and report violations without blocking anything.
  • Set CSP_ENFORCE=true in the deploy environment to promote to enforcing Content-Security-Policy, no code change required.
  • Allow-list covers Next's inline hydration scripts, inline component styles, Sentry ingest, and Vercel Blob.

Test plan

  • pnpm typecheck clean
  • Observe zero CSP violations in staging before flipping CSP_ENFORCE=true
  • Verify CI green on this PR

Summary by CodeRabbit

  • New Features

    • Added Content Security Policy headers across application responses.
    • CSP runs in Report-Only mode by default outside production and can be enforced with CSP_ENFORCE=true.
    • Production CSP includes protection against insecure requests.
  • Documentation

    • Updated security audit and post-launch tracking to reflect CSP’s Report-Only status and enforcement steps.
    • Documented the new CSP configuration setting.

Ships a CSP in Report-Only mode by default so it cannot break the live
site; browsers evaluate the policy and surface violations without
blocking. Set CSP_ENFORCE=true in the deploy environment to promote it
to an enforcing Content-Security-Policy header after staging confirms
zero violations — no code change required.

Allow-list rationale is documented inline in next.config.ts:
- script-src/style-src allow 'unsafe-inline' (Next App Router inline
  hydration scripts + inline style={{…}} in 19 components); 'unsafe-eval'
  is dev-only for React Fast Refresh.
- img-src is permissive (https:) because lesson MDX renders via
  dangerouslySetInnerHTML and may reference arbitrary image hosts.
- connect-src covers Sentry ingest and Vercel Blob.
- frame-ancestors 'none' mirrors the existing X-Frame-Options: DENY.

Documents the CSP_ENFORCE flag in .env.example and updates the audit +
handover docs to reflect O5 as Report-Only shipped, enforce pending.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018nEP4xYTgNh2JdLjTRNnYZ
Copilot AI review requested due to automatic review settings July 20, 2026 04:22

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.

@coderabbitai

coderabbitai Bot commented Jul 20, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

Adds an environment-controlled Content-Security-Policy generator to Next.js, applies the selected header to all path responses, and documents report-only defaults, enforcement instructions, and rollout status.

Changes

CSP rollout

Layer / File(s) Summary
CSP generation and response wiring
next.config.ts
Builds CSP directives, selects enforcing or Report-Only mode using CSP_ENFORCE, adds production-only upgrade-insecure-requests, and applies the header through securityHeaders.
CSP configuration and rollout documentation
.env.example, SESSION-HANDOVER.md, docs/security/code-audit-2026-07-15.md
Documents the default Report-Only mode, CSP_ENFORCE=true, staging validation, and the remaining reporting-sink follow-up.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Sequence Diagram(s)

sequenceDiagram
  participant CSP_ENFORCE environment
  participant next.config.ts
  participant HTTP response
  CSP_ENFORCE environment->>next.config.ts: Select CSP enforcement mode
  next.config.ts->>HTTP response: Add Content-Security-Policy or Report-Only header
Loading

Suggested reviewers: copilot

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely summarizes the main change: adding a Content-Security-Policy header for audit O5.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch claude/remaining-todos-muoxgh

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot 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.

Actionable comments posted: 2

🧹 Nitpick comments (1)
next.config.ts (1)

34-44: 🔒 Security & Privacy | 🔵 Trivial

No report-to/report-uri sink configured for the Report-Only phase.

The rollout comment says violations get "reported without blocking the site," but without a report-to/report-uri directive there's no systematic collection channel — violations only surface in an individual browser's devtools console. That makes "confirm zero violations in staging" (the documented gate for flipping CSP_ENFORCE) hard to verify reliably across pages/browsers. This is already tracked as a follow-up in the rollout docs, so flagging for visibility rather than as a blocker.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@next.config.ts` around lines 34 - 44, Update the CSP directives configuration
to add a reporting sink for report-only violations, using the project’s
documented report-to or report-uri endpoint/configuration. Keep the existing
source and enforcement directives unchanged, and ensure the sink is available
during the staging rollout used to verify violations before enabling
CSP_ENFORCE.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@next.config.ts`:
- Around line 23-51: Add unit tests for contentSecurityPolicy() covering
production versus non-production behavior for 'unsafe-eval' and
upgrade-insecure-requests, plus CSP_ENFORCE-driven selection of the response
header key. Ensure tests isolate and restore NODE_ENV and CSP_ENFORCE so they do
not affect other configuration tests.
- Around line 10-12: Update the comment in the CSP configuration guidance to
replace the em-dash between “header” and “no code change required” with
punctuation permitted by the coding guidelines, preserving the original meaning.

---

Nitpick comments:
In `@next.config.ts`:
- Around line 34-44: Update the CSP directives configuration to add a reporting
sink for report-only violations, using the project’s documented report-to or
report-uri endpoint/configuration. Keep the existing source and enforcement
directives unchanged, and ensure the sink is available during the staging
rollout used to verify violations before enabling CSP_ENFORCE.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 0c2d866e-1470-428a-92fc-7915ea2dbd53

📥 Commits

Reviewing files that changed from the base of the PR and between 78f1931 and f7fee3b.

📒 Files selected for processing (4)
  • .env.example
  • SESSION-HANDOVER.md
  • docs/security/code-audit-2026-07-15.md
  • next.config.ts

Comment thread next.config.ts
Comment on lines +10 to +12
// everything. Once staging has been observed to produce zero violations, set
// `CSP_ENFORCE=true` in the deploy environment to promote it to an enforcing
// `Content-Security-Policy` header — no code change required.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Remove the em-dash.

Line 12 uses an em-dash ("header — no code change required"). As per coding guidelines, **/*.{ts,tsx,js,jsx}: "do not use em-dashes. Use periods, commas, or parentheses instead."

Proposed fix
-// `Content-Security-Policy` header — no code change required.
+// `Content-Security-Policy` header (no code change required).
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
// everything. Once staging has been observed to produce zero violations, set
// `CSP_ENFORCE=true` in the deploy environment to promote it to an enforcing
// `Content-Security-Policy` header no code change required.
// everything. Once staging has been observed to produce zero violations, set
// `CSP_ENFORCE=true` in the deploy environment to promote it to an enforcing
// `Content-Security-Policy` header (no code change required).
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@next.config.ts` around lines 10 - 12, Update the comment in the CSP
configuration guidance to replace the em-dash between “header” and “no code
change required” with punctuation permitted by the coding guidelines, preserving
the original meaning.

Source: Coding guidelines

Comment thread next.config.ts
Comment on lines +23 to +51
function contentSecurityPolicy(): string {
const isProd = process.env.NODE_ENV === 'production';
const scriptSrc = ["'self'", "'unsafe-inline'"];
if (!isProd) scriptSrc.push("'unsafe-eval'");

const directives: Record<string, string[]> = {
'default-src': ["'self'"],
'script-src': scriptSrc,
'style-src': ["'self'", "'unsafe-inline'"],
'img-src': ["'self'", 'data:', 'blob:', 'https:'],
'font-src': ["'self'", 'data:'],
'connect-src': [
"'self'",
'https://*.sentry.io',
'https://*.ingest.sentry.io',
'https://*.blob.vercel-storage.com',
],
'frame-ancestors': ["'none'"],
'base-uri': ["'self'"],
'form-action': ["'self'"],
'object-src': ["'none'"],
};

const parts = Object.entries(directives).map(
([name, values]) => `${name} ${values.join(' ')}`,
);
if (isProd) parts.push('upgrade-insecure-requests');
return parts.join('; ');
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick win

No tests added for the new contentSecurityPolicy() logic.

This is a new feature (env-sensitive directive builder with prod/dev and CSP_ENFORCE branching). As per coding guidelines, **/*.{ts,tsx,md,mdx}: "New features must include tests." A small unit test asserting 'unsafe-eval'/upgrade-insecure-requests toggle correctly with NODE_ENV, and that the header key switches on CSP_ENFORCE, would catch regressions cheaply given this is a security-relevant config.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@next.config.ts` around lines 23 - 51, Add unit tests for
contentSecurityPolicy() covering production versus non-production behavior for
'unsafe-eval' and upgrade-insecure-requests, plus CSP_ENFORCE-driven selection
of the response header key. Ensure tests isolate and restore NODE_ENV and
CSP_ENFORCE so they do not affect other configuration tests.

Source: Coding guidelines

@projectamazonph
projectamazonph merged commit e1a70ce into main Jul 20, 2026
5 checks passed
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.

3 participants