Environment
- Operating System: Linux
- Node Version: v22.11.0
- Nuxt Version: 3.14.1592
- CLI Version: 3.17.2
- Nitro Version: 2.10.4
- Package Manager: yarn@1.22.22
- Builder: -
- User Config: default
- Runtime Modules: nuxt-security@2.1.5
- Build Modules: -
Nuxt Security Version
v2.1.5
Default setup used?
Yes, the bug happens even if the security option is not customized
Security options
Reproduction
https://github.com/maple3142/nuxt-security-nonce-bug-repro
yarn install && yarn build
node .output/server/index.mjs
- Visit
http://localhost:3000/?statusMessage=1&html=%3Cdiv+id=%22%3Cscript%3E%3Cscript%3Ealert(origin)%3C/script%3E%22%3E%3C/div%3E from browser
Description
The browser would pop an alert when visiting that url (so XSS happens here), despite https://github.com/maple3142/nuxt-security-nonce-bug-repro/blob/master/pages/index.vue does sanitize the incoming html using DOMPurify.
The main problem is that nuxt security incorrectly add nonces to script tags using simple string replacement here: https://github.com/nuxt-modules/security/blob/70cd67a4690b53e9167c210e3e020faed901355d/src/runtime/nitro/plugins/40-cspSsrNonce.ts#L53-L73 . And v-html can result in unescaped <script> to appear in rendered html in SSR mode.
I think nuxt-security should not process html in from v-html, and should not naively use string replacement to do that because it may accidentally replace fake script tags inside element attributes.
Additional context
No response
Logs
Environment
Nuxt Security Version
v2.1.5
Default setup used?
Yes, the bug happens even if the security option is not customized
Security options
Reproduction
https://github.com/maple3142/nuxt-security-nonce-bug-repro
yarn install && yarn buildnode .output/server/index.mjshttp://localhost:3000/?statusMessage=1&html=%3Cdiv+id=%22%3Cscript%3E%3Cscript%3Ealert(origin)%3C/script%3E%22%3E%3C/div%3Efrom browserDescription
The browser would pop an alert when visiting that url (so XSS happens here), despite https://github.com/maple3142/nuxt-security-nonce-bug-repro/blob/master/pages/index.vue does sanitize the incoming html using DOMPurify.
The main problem is that nuxt security incorrectly add nonces to script tags using simple string replacement here: https://github.com/nuxt-modules/security/blob/70cd67a4690b53e9167c210e3e020faed901355d/src/runtime/nitro/plugins/40-cspSsrNonce.ts#L53-L73 . And
v-htmlcan result in unescaped<script>to appear in rendered html in SSR mode.I think nuxt-security should not process html in from v-html, and should not naively use string replacement to do that because it may accidentally replace fake script tags inside element attributes.
Additional context
No response
Logs