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 theContent-Security-Policyheader and a customx-nonceheader. - 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.jsvia theheaders()config. - Experimental hash-based CSP via Subresource Integrity, which keeps static generation intact.
Setting the header¶
Report-only is the safe starting point. Your URLs come from the Setup page:
const cspHeader = `
default-src 'self';
script-src 'self' 'nonce-${nonce}' 'strict-dynamic' 'report-sha256';
object-src 'none';
base-uri 'self';
report-uri https://abc123.report-uri.com/r/d/csp/reportOnly;
report-to default;
`
response.headers.set(
'Content-Security-Policy-Report-Only',
cspHeader.replace(/\s{2,}/g, ' ').trim(),
)
response.headers.set('Reporting-Endpoints', 'default="https://abc123.report-uri.com/a/d/g"')
response.headers.set('Report-To', JSON.stringify({
group: 'default',
max_age: 31536000,
endpoints: [{ url: 'https://abc123.report-uri.com/a/d/g' }],
include_subdomains: true,
}))
The Reporting-Endpoints and Report-To headers tell the browser where report-to default sends reports, including the CSP Integrity reports that 'report-sha256' turns on.
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 usesevalfor better error stacks. It is not required in production - gate it onNODE_ENVrather 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
integrityattributes, so pages stay cacheable. - A
<meta>tag policy cannot carryreport-uriorreport-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 CSP reporting directives on Setup, or view your CSP reports.
New to Report URI? Create an account and grab your CSP reporting directives from the Setup page.