Skip to content

fix(security): strict CSP with SRI — script-src 'self' without unsafe-inline - #311

Merged
ety001 merged 1 commit into
nextfrom
fix/csp-sri-script-src
Aug 6, 2026
Merged

fix(security): strict CSP with SRI — script-src 'self' without unsafe-inline#311
ety001 merged 1 commit into
nextfrom
fix/csp-sri-script-src

Conversation

@ety001

@ety001 ety001 commented Aug 6, 2026

Copy link
Copy Markdown
Member

Summary

Closes audit V2 finding V2-14 (Low): the app had no script-src CSP — only frame-ancestors 'none'. For a wallet that stores posting keys in localStorage and active/owner keys in Redux memory, any XSS = key exfiltration with no CSP backstop.

Approach: Subresource Integrity (SRI)

Next.js experimental SRI generates SHA-256 hashes for all JS bundles at build time. Browsers verify integrity via <script integrity="sha256-..."> attributes, so script-src 'self' suffices — no unsafe-inline needed.

Why SRI over nonce-based CSP:

  • Zero performance impact — preserves static generation, ISR, and CDN caching
  • No dynamic rendering required — nonce-based CSP forces all pages to dynamic rendering, killing static optimization
  • No middleware changes — works entirely in next.config.ts
  • The app already has src/proxy.ts, but SRI avoids the dynamic-rendering penalty

Changes (next.config.ts only)

  • Enable experimental.sri.algorithm: 'sha256'
  • Upgrade CSP from frame-ancestors 'none' to full policy:
    script-src 'self'                      (no unsafe-inline in production!)
    style-src 'self' 'unsafe-inline'       (Tailwind/charts)
    img-src 'self' blob: data:
    connect-src 'self'
    object-src 'none'
    base-uri 'self'
    form-action 'self'
    frame-ancestors 'none'
    upgrade-insecure-requests
    
  • Development adds 'unsafe-eval' (React DevTools); production has neither.

Verification

  • SRI confirmed working: every <script> tag in build output has integrity="sha256-..." attribute
  • Build succeeds (static + dynamic pages render correctly)
  • No runtime errors

Trade-offs

  • SRI is an experimental Next.js feature (may change in future versions)
  • If SRI breaks in a future Next.js upgrade, can revert to the previous frame-ancestors-only policy with no regression

Test plan

  • pnpm type-check — clean
  • pnpm lint — 0 errors
  • pnpm test — 477 passed
  • pnpm build — succeeds, SRI integrity attributes present in output

…-inline

Enable Next.js experimental Subresource Integrity (SRI) to generate SHA-256
hashes for all JS bundles at build time. Browsers verify file integrity via
the integrity attribute, so the CSP can use script-src 'self' without
'unsafe-inline' — any attacker-injected inline script is blocked.

Upgrade the CSP from the previous frame-ancestors-only policy to a full
directive set: default-src, script-src, style-src, img-src, font-src,
connect-src, object-src, base-uri, form-action, frame-ancestors, and
upgrade-insecure-requests. Development adds 'unsafe-eval' (React DevTools);
production has neither 'unsafe-inline' nor 'unsafe-eval' for scripts.

SRI preserves static generation, ISR, and CDN caching — no nonce or dynamic
rendering required, zero performance impact.

This closes the audit V2 finding: the wallet stores posting keys in
localStorage and active/owner keys in Redux memory, so a strict script-src
is critical defense-in-depth against XSS.
@ety001
ety001 merged commit df5076c into next Aug 6, 2026
2 of 3 checks passed
@ety001
ety001 deleted the fix/csp-sri-script-src branch August 6, 2026 16:12
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.

1 participant