From 3736277e55191cbdaa94f7511da8af216d5de820 Mon Sep 17 00:00:00 2001 From: Birk Skyum Date: Sun, 26 Jul 2026 17:06:46 +0200 Subject: [PATCH] fix: apply nonce to streaming redirect and SPA entry scripts --- .changeset/lucky-moths-nonce.md | 8 ++++++++ packages/start/src/server/handler.ts | 12 +++++++++++- packages/start/src/server/spa/StartServer.tsx | 1 + 3 files changed, 20 insertions(+), 1 deletion(-) create mode 100644 .changeset/lucky-moths-nonce.md diff --git a/.changeset/lucky-moths-nonce.md b/.changeset/lucky-moths-nonce.md new file mode 100644 index 000000000..27dd7be09 --- /dev/null +++ b/.changeset/lucky-moths-nonce.md @@ -0,0 +1,8 @@ +--- +"@solidjs/start": patch +--- + +Apply the configured `nonce` to the two script tags that were still missing it, so a strict `script-src` CSP no longer needs `unsafe-inline`: + +- The client-side redirect that streaming mode emits after the shell has already flushed (``) now carries the nonce. +- The SPA entry script tag now carries the nonce, matching the SSR entry script. diff --git a/packages/start/src/server/handler.ts b/packages/start/src/server/handler.ts index d4fb6e4b7..18f2ddca5 100644 --- a/packages/start/src/server/handler.ts +++ b/packages/start/src/server/handler.ts @@ -210,10 +210,20 @@ function handleStreamCompleteRedirect(context: PageEvent) { return ({ write }: { write: (html: string) => void }) => { context.complete = true; const to = context.response && context.response.headers.get("Location"); - to && write(``); + if (!to) return; + // The shell has already flushed, so the redirect has to happen client side. + // Carry the nonce so a strict `script-src` CSP doesn't block it. + const nonce = context.nonce ? ` nonce="${escapeAttribute(context.nonce)}"` : ""; + write( + `window.location=${JSON.stringify(to).replace(/`, + ); }; } +function escapeAttribute(value: string) { + return value.replace(/&/g, "&").replace(/"/g, """).replace(/