Skip to content

Commit c8615ed

Browse files
authored
fix: apply nonce to generated client entry (#311)
1 parent 450d0e5 commit c8615ed

3 files changed

Lines changed: 23 additions & 3 deletions

File tree

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@solidjs/vite-plugin': patch
3+
---
4+
5+
Apply the request CSP nonce to start mode's generated client-entry script.

examples/turnkey/test/run.mjs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -951,6 +951,16 @@ async function runProdMode() {
951951
fetchableHtml.includes('SSR Start Mode') &&
952952
!fetchableHtml.includes('provider-argument-must-not-be-forwarded'),
953953
);
954+
const nonceResponse = await builtHandler.handleRequest(new Request(origin + '/'), {
955+
nonce: 'test"<&',
956+
});
957+
const nonceHtml = await nonceResponse.text();
958+
record(
959+
mode,
960+
'build',
961+
'client entry carries the escaped CSP nonce',
962+
nonceHtml.includes('<script type="module" nonce="test&quot;&lt;&amp;" src="'),
963+
);
954964
record(
955965
mode,
956966
'build',

src/ssr/index.ts

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -721,7 +721,12 @@ export function startServe(
721721
// every positional claim after it.
722722
lines.push(
723723
``,
724-
`function createHtmlChunkTransform(clientEntry, extraHead) {`,
724+
`function escapeAttribute(value) {`,
725+
` return value.replace(/&/g, '&amp;').replace(/"/g, '&quot;').replace(/</g, '&lt;');`,
726+
`}`,
727+
``,
728+
`function createHtmlChunkTransform(clientEntry, extraHead, nonce) {`,
729+
` const nonceAttr = nonce ? ' nonce="' + escapeAttribute(nonce) + '"' : '';`,
725730
` let first = true;`,
726731
` let injected = false;`,
727732
` return (chunk) => {`,
@@ -767,7 +772,7 @@ export function startServe(
767772
// fresh render-into-body mount (hydration, by contrast, wants to
768773
// start as early as possible).
769774
headParts.push(
770-
`(clientEntry ? '<script type="module" src="' + clientEntry + '"${clientMode ? '' : ' async'}></' + 'script>' : '')`,
775+
`(clientEntry ? '<script type="module"' + nonceAttr + ' src="' + clientEntry + '"${clientMode ? '' : ' async'}></' + 'script>' : '')`,
771776
);
772777
}
773778
if (headParts.length) {
@@ -851,7 +856,7 @@ export function startServe(
851856
` return createSSRResponse(result, event, {`,
852857
` responseInit: options.responseInit,`,
853858
` nonce: options.nonce,`,
854-
` transformChunk: createHtmlChunkTransform(clientEntry, options.devHead),`,
859+
` transformChunk: createHtmlChunkTransform(clientEntry, options.devHead, options.nonce),`,
855860
` });`,
856861
`}`,
857862
``,

0 commit comments

Comments
 (0)