Skip to content

fix: accept the { script, style } CSP nonce in handleRequest - #392

Open
everton-dgn wants to merge 1 commit into
solidjs:nextfrom
everton-dgn:fix/csp-nonce-object-form
Open

everton-dgn wants to merge 1 commit into
solidjs:nextfrom
everton-dgn:fix/csp-nonce-object-form

Conversation

@everton-dgn

Copy link
Copy Markdown

Problem

handleRequest(request, { nonce }) throws when the nonce is the { script, style } form of @solidjs/web's CSPNonce:

TypeError: value.replace is not a function

The generated handler passes options.nonce unchanged to createHtmlChunkTransform, whose escapeAttribute calls .replace on it, and to createSSRResponse, whose nonce option is typed string. @solidjs/web documents that its single-script surfaces (HydrationScript, generateHydrationScript, createSSRResponse) take a string and that a CSPNonce is projected with scriptNonce.

The option is also missing from the virtual:solid-ssr-handler types, so a typed caller gets TS2353 for nonce although the handler reads it.

This is the bug fix from #389 on its own, so it can land without the start.nonce feature (#388).

Fix

  • The generated handler projects the option with scriptNonce before both uses. A string behaves as before, a pair contributes its script value, and script: false leaves both tags without a nonce.
  • virtual-solid-manifest.d.ts declares nonce?: CSPNonce on the handleRequest options and names the two tags it reaches.

What the nonce reaches doesn't change: the generated entry still renders without it, which is #388.

A value outside the type (a number, an object without script) threw the same TypeError before. It now leaves the tags without a nonce, since scriptNonce returns undefined for it. #389 rejects such values with an error that names their source.

Verification

Four assertions in the prod mode of examples/start-ssr/test/run.mjs, next to the nonce check from #311. A pair puts its script nonce, never its style one, on the client-entry tag and on the post-flush redirect fallback (/redirect-post). { script: false, style } leaves both without a nonce. On next (e4cdee4) the prod mode ends at 63/67, with the four new checks throwing TypeError: value.replace is not a function. On this branch it passes 67/67.

With the fix, pnpm test in examples/start-ssr passes (run.mjs 649/649, http-bridge 10/10, components-warning 11/11, webworker-warning 12/12, dedupe 8/8), and so does examples/start-client (65/65).

For the types, a scratch tsc project over virtual-solid-manifest.d.ts accepts a string and both pair shapes and rejects { script } alone and a number. Against next's declarations the three valid calls fail with TS2353.

The generated handler passed `options.nonce` unchanged to the
client-entry transform, whose `escapeAttribute` calls `.replace` on it,
and to `createSSRResponse`, which takes a string, so a `{ script, style }`
nonce threw `TypeError: value.replace is not a function`. Project it with
`scriptNonce` for both, and declare the option in the
`virtual:solid-ssr-handler` types.
@changeset-bot

changeset-bot Bot commented Oct 3, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 970bc19

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
@solidjs/vite-plugin Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant