Description
Vite currently supports html.cspNonce as a single shared nonce placeholder.
This works for many setups, but some CSP integrations generate separate nonces for script-src and style-src. A concrete example is @fastify/helmet: with enableCSPNonces: true, it exposes:
reply.cspNonce.script
reply.cspNonce.style
and adds them to script-src and style-src respectively.
With the current Vite API, users either need to collapse both values into one nonce or add custom handling around Vite-generated tags.
Suggested solution
Allow html.cspNonce to accept either the current string value or a split object:
export default defineConfig({
html: {
cspNonce: {
script: '__SCRIPT_NONCE__',
style: '__STYLE_NONCE__',
},
},
})
Expected behavior:
string keeps the current shared nonce behavior;
script nonce is used for scripts and script preloads;
style nonce is used for styles and style preloads;
- existing
meta[property="csp-nonce"] integrations keep working as fallback.
Alternative
A partial workaround is to avoid using Vite's single nonce for scripts and rely on script-src 'nonce-...' 'strict-dynamic' for script loading, while using the existing Vite nonce meta tag only for style-related runtime injections:
<meta property="csp-nonce" nonce="STYLE_CSP_NONCE" />
This can make style preloads work because Vite reads meta[property="csp-nonce"] when injecting runtime preload/style links.
However, this is a split and implicit setup.
Additional context
I have an open PR with a possible implementation in Vite core: #22289
It keeps the existing shared html.cspNonce behavior and adds an opt-in { script, style } mode for split CSP nonce setups.
Validations
Description
Vite currently supports
html.cspNonceas a single shared nonce placeholder.This works for many setups, but some CSP integrations generate separate nonces for
script-srcandstyle-src. A concrete example is@fastify/helmet: withenableCSPNonces: true, it exposes:and adds them to
script-srcandstyle-srcrespectively.With the current Vite API, users either need to collapse both values into one nonce or add custom handling around Vite-generated tags.
Suggested solution
Allow
html.cspNonceto accept either the current string value or a split object:Expected behavior:
stringkeeps the current shared nonce behavior;scriptnonce is used for scripts and script preloads;stylenonce is used for styles and style preloads;meta[property="csp-nonce"]integrations keep working as fallback.Alternative
A partial workaround is to avoid using Vite's single nonce for scripts and rely on
script-src 'nonce-...' 'strict-dynamic'for script loading, while using the existing Vite nonce meta tag only for style-related runtime injections:This can make style preloads work because Vite reads
meta[property="csp-nonce"]when injecting runtime preload/style links.However, this is a split and implicit setup.
Additional context
I have an open PR with a possible implementation in Vite core: #22289
It keeps the existing shared
html.cspNoncebehavior and adds an opt-in{ script, style }mode for split CSP nonce setups.Validations