Skip to content
MDView as Markdown

Next.js

Next.js has the most complete CSP story of any framework here, and also the most honest one: it documents not just how to add a nonce, but what adopting one costs you. That trade-off is the thing to understand before you start.

What Next.js gives you

  • Nonce generation in the proxy layer (proxy.ts, previously middleware), set on both the Content-Security-Policy header and a custom x-nonce header.
  • Automatic nonce application during server-side rendering. Next.js parses the CSP header, extracts the 'nonce-{value}' pattern, and attaches it to framework scripts, page bundles, its own inline styles and scripts, and any <Script> component - you do not tag them by hand.
  • headers() in a Server Component for reading the nonce back, e.g. to pass to <GoogleTagManager nonce={nonce} />.
  • A no-nonce route: set the header statically in next.config.js via the headers() config.
  • Experimental hash-based CSP via Subresource Integrity, which keeps static generation intact.

Setting the header

Report-only is the safe starting point. Your URL comes from the Setup page:

const cspHeader = `
  default-src 'self';
  script-src 'self' 'nonce-${nonce}' 'strict-dynamic';
  object-src 'none';
  base-uri 'self';
  report-uri https://abc123.report-uri.com/r/d/csp/reportOnly;
`
response.headers.set(
  'Content-Security-Policy-Report-Only',
  cspHeader.replace(/\s{2,}/g, ' ').trim(),
)

Filter the proxy with a matcher so it skips API routes, _next/static, _next/image and prefetches - those do not need the header and generating a nonce for them is wasted work.

Things to watch for

  • Nonces force dynamic rendering. Static optimisation and ISR are disabled, pages cannot be CDN-cached by default, and Partial Prerendering is incompatible because the static shell has no access to the nonce. This is a real architectural cost, not a footnote.
  • 'unsafe-eval' is required in development because React uses eval for better error stacks. It is not required in production - gate it on NODE_ENV rather than shipping it.
  • If you need to keep static generation, the experimental SRI support is the alternative: hashes are generated at build time and added as integrity attributes, so pages stay cacheable.
  • A <meta> tag policy cannot carry report-uri or report-to. If you want reports, the policy has to be a header.

Official documentation

Next.js - How to set a Content Security Policy (CSP) for your Next.js application

Start Monitoring with Report URI

Already using us for CSP? Find your report-uri value on Setup, or view your CSP reports.

New to Report URI? Create an account and grab your report-uri value from the Setup page.

Start your free trial