Baroshem / nuxt-security

🛡 Automatically configure your app to follow OWASP security patterns and principles by using HTTP Headers and Middleware
https://nuxt-security.vercel.app/
MIT License
738 stars 56 forks source link

Cannot use nonce in nuxt-security:headers hook #407

Closed jackpercy-acl closed 2 months ago

jackpercy-acl commented 3 months ago

Version

nuxt-security: 1.2.2 nuxt: 3.11.1

Reproduction Link

https://stackblitz.com/edit/nuxt-security-missing-nonce?file=server%2Fplugins%2Fsecurity.ts

Steps to reproduce

  1. Configure the nuxt-security:headers hook to change CSP with Runtime Config as per docs
  2. Include a 'nonce-{{nonce}}' value in one of the CSP values
export default defineNitroPlugin((nitroApp) => {
  nitroApp.hooks.hook('nuxt-security:ready', async () => {
    await nitroApp.hooks.callHook('nuxt-security:headers', {
      route: '/**',
      headers: {
        contentSecurityPolicy: {
          'script-src': [
            "'self'",
            'https:',
            "'unsafe-inline'",
            "'strict-dynamic'",
            "'nonce-{{nonce}}'",
          ],
        },
      },
    });
  });
});

What is Expected?

The CSP header should be transformed to include the actual nonce value.

What is actually happening?

The CSP value contains the exact string 'nonce-{{nonce}}'

image

By adding some logging into the nuxt-security nitro plugins files, you can see that the custom CSP from the hook is being registered. However, when the plugin 99-cspSsrNonce.ts runs, the CSP value it resolves and replaces the nonces in, is the default/nuxt.config.ts CSP.

https://github.com/Baroshem/nuxt-security/blob/13a96a6e36989a277cb046b379bb65a251e04afc/src/runtime/nitro/plugins/99-cspSsrNonce.ts#L43

This is meaning we cannot do a combination of using runtime config in the CSP and nonces.

Baroshem commented 3 months ago

Hey, thanks for reporting this.

@vejja @huang-julien do you have some ideas about it? :)

vejja commented 3 months ago

@jackpercy-acl : does it work if you don't use the runtime config and instead use the default nuxt.config.ts ?

jackpercy-acl commented 3 months ago

@vejja yes, it works fine if configuring only in nuxt.config.ts

image

image

vejja commented 3 months ago

Thanks @huang-julien looks like the runtime config is not picked up here ?

huang-julien commented 3 months ago

I'm not sure about that, I can't reproduce it image

I may have to try reproduce it locally

jackpercy-acl commented 3 months ago

@huang-julien if you check the headers on the returned doc rather than logging render:response you will see the unset nonce.

I assume this beforeResponse hook is run after render:response which is when the CSP from the nuxt-security:headers hook is set on the response.

https://github.com/Baroshem/nuxt-security/blob/13a96a6e36989a277cb046b379bb65a251e04afc/src/runtime/nitro/plugins/00-context.ts#L35