You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The repo is a bare App Router app: one client component (app/counter.tsx) to force inline flight scripts + hydration, and the SRI + strict CSP config in next.config.ts.
Current vs. Expected behavior
Current: every inline flight script is blocked, so the page never hydrates (the counter button stays at count is 0 and never increments). Console shows repeated:
Executing inline script violates the following Content Security Policy directive 'script-src 'self''.
Either the 'unsafe-inline' keyword, a hash ('sha256-…'), or a nonce ('nonce-…') is required to enable inline execution.
The action has been blocked.
The blocked scripts are the inline flight payload (self.__next_f.push). Inspecting the served HTML: external <script src> tags carry integrity="sha256-…" (from SRI), but the inline flight scripts carry none.
Expected: with experimental.sri enabled, the framework's own inline flight scripts should be trusted under a strict CSP without 'unsafe-inline' — e.g. by attaching an integrity attribute to each inline flight script the same way external scripts are handled. Since these scripts are generated server-side, their hash is knowable at emit time.
Root cause (traced in next@16.2.9, matches canary)
Next splits scripts into two paths:
External <script src> get integrity from the SRI manifest, keyed by filename:
SubresourceIntegrityPlugin is a webpack plugin that hashes emitted assets (compilation.getAssets()), so it can't see the per-request inline flight scripts — SRI is external-only by design.
Why this matters
For any App Router page that streams inline flight scripts, the inline scripts have exactly three CSP options today, none of which is both strict and cacheable:
Nonce — the only mechanism inline scripts support today, but the nonce is read from the request CSP header at render time (get-script-nonce-from-header.js), forcing dynamic rendering and Cache-Control: no-store → no CDN caching. (See Nonce-based CSP with inline <head> scripts is incompatible with cacheComponents #89754 for the cacheComponents/PPR side.)
'unsafe-inline' — works and stays cacheable, but defeats a strict CSP.
Hash the inline content yourself post-build — unsupported and fragile (content is per-page / per-build).
Attaching integrity to the inline flight scripts would provide a fourth, working option: strict CSP, no nonce, fully cacheable.
Also worth clarifying in the docs' "Without Nonces / SRI" section — it reads as though SRI lets you drop 'unsafe-inline' for a static page, but it only does so for external scripts; the inline flight scripts still break.
Provide environment information
Operating System:
Platform: darwin
Arch: arm64
Version: Darwin Kernel Version 25.3.0
Available memory (MB): 36864
Available CPU cores: 14
Binaries:
Node: 24.13.0
npm: 11.6.2
pnpm: 9.15.9
Relevant Packages:
next: 16.2.9 // Latest available version is detected (16.2.9).
react: 19.2.0
react-dom: 19.2.0
typescript: 5.9.3
Next.js Config:
output: N/A
Which area(s) are affected? (Select all that apply)
Not sure / other (CSP / experimental.sri / App Router rendering)
Which stage(s) are affected? (Select all that apply)
next build (local), next start (local)
Additional context
Reproduces with cacheComponents off (not in the config), so this is purely SRI not covering inline flight scripts. Bundler: Turbopack.
Link to the code that reproduces this issue
https://github.com/bearpong/nextjs-sri-inline-csp-repro
To Reproduce
git clone https://github.com/bearpong/nextjs-sri-inline-csp-repro && cd nextjs-sri-inline-csp-repronpm installnpm run build(SRI is enabled viaexperimental.sri, strict CSP set viaheaders()—script-src 'self', no'unsafe-inline', no nonce)npm start— must be a production build;next devmasks itThe repo is a bare App Router app: one client component (
app/counter.tsx) to force inline flight scripts + hydration, and the SRI + strict CSP config innext.config.ts.Current vs. Expected behavior
Current: every inline flight script is blocked, so the page never hydrates (the counter button stays at
count is 0and never increments). Console shows repeated:The blocked scripts are the inline flight payload (
self.__next_f.push). Inspecting the served HTML: external<script src>tags carryintegrity="sha256-…"(from SRI), but the inline flight scripts carry none.You can confirm without a browser:
Expected: with
experimental.srienabled, the framework's own inline flight scripts should be trusted under a strict CSP without'unsafe-inline'— e.g. by attaching anintegrityattribute to each inline flight script the same way external scripts are handled. Since these scripts are generated server-side, their hash is knowable at emit time.Root cause (traced in
next@16.2.9, matchescanary)Next splits scripts into two paths:
<script src>getintegrityfrom the SRI manifest, keyed by filename:next/dist/server/app-render/required-scripts.js→bootstrapScript.integrity = SRIManifest[files[0]]app-render.jspolyfills →integrity: subresourceIntegrityManifest?.[polyfill]self.__next_f.push) — the tag is built with only anonce(if present), never anintegrity:next/dist/server/app-render/use-flight-response.js→const startScriptTag = nonce ? \<script nonce="…">` : "<script>"`SubresourceIntegrityPluginis a webpack plugin that hashes emitted assets (compilation.getAssets()), so it can't see the per-request inline flight scripts — SRI is external-only by design.Why this matters
For any App Router page that streams inline flight scripts, the inline scripts have exactly three CSP options today, none of which is both strict and cacheable:
get-script-nonce-from-header.js), forcing dynamic rendering andCache-Control: no-store→ no CDN caching. (See Nonce-based CSP with inline <head> scripts is incompatible with cacheComponents #89754 for thecacheComponents/PPR side.)'unsafe-inline'— works and stays cacheable, but defeats a strict CSP.Attaching
integrityto the inline flight scripts would provide a fourth, working option: strict CSP, no nonce, fully cacheable.Also worth clarifying in the docs' "Without Nonces / SRI" section — it reads as though SRI lets you drop
'unsafe-inline'for a static page, but it only does so for external scripts; the inline flight scripts still break.Provide environment information
Which area(s) are affected? (Select all that apply)
Not sure / other (CSP /
experimental.sri/ App Router rendering)Which stage(s) are affected? (Select all that apply)
next build(local),next start(local)Additional context
Reproduces with
cacheComponentsoff (not in the config), so this is purely SRI not covering inline flight scripts. Bundler: Turbopack.