Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Nonce attributes values are erased during application boot - SSR mode #427

Open
BnitoBzh opened this issue Apr 17, 2024 · 12 comments
Open
Labels
awaiting details Waiting for feedback from the issue author, i.e. reproduction
Milestone

Comments

@BnitoBzh
Copy link

Version

nuxt-security: 1.3.2
nuxt: 3.11.2

Reproduction Link

Nothing

Steps to reproduce

Nothing

What is Expected?

Nuxt must render the page in SSR mode with all nonce attributes set on each script tag.

What is actually happening?

When Nuxt render the page in SSR mode, all nonce attributes are set. i am using the browser utlity "show the page source", this is OK !
But when the page is fully loaded and the Nuxt app is running, the developer tools shows that all nonce attribute values are empty ...
This cause multiple issue with CSP ...

Here is my nuxt config file :

// https://nuxt.com/docs/api/configuration/nuxt-config

export default defineNuxtConfig({
    devtools: {enabled: process.env.NODE_ENV !== 'production'},
    ssr: process.env.NODE_ENV === 'production',

    runtimeConfig: {
        public: {
            contentfulSpaceId: process.env.CONTENTFUL_SPACE_ID,
            contentfulAccessToken: process.env.CONTENTFUL_ACCESS_TOKEN,
            contentfulHomePageId: process.env.CONTENTFUL_HOME_PAGE_ID,

            gtm: {
                id: process.env.GTM_ID!,
                /*queryParams: {
                    gtm_auth: '',
                    gtm_preview: '',
                    gtm_cookies_win: '',
                },*/
                defer: false,
                compatibility: false,
                // nonce: '2726c7f26c',
                enabled: process.env.NODE_ENV === 'production',
                debug: process.env.NODE_ENV !== 'production',
                loadScript: false,
                enableRouterSync: true,
                ignoredViews: [],
                trackOnNextTick: false,
                devtools: true,
            }
        },
    },

    modules: [
        '@zadigetvoltaire/nuxt-gtm',
        '@nuxtjs/tailwindcss',
        'nuxt-security',
    ],

    tailwindcss: {
        exposeConfig: true,
        viewer: true,
    },

    app: {
        head: {
            charset: 'utf-8',
            viewport: 'width=device-width, initial-scale=1',
            script: [
                ...(process.env.NODE_ENV === 'production' ? [
                    // GTM
                    {
                        type: 'text/javascript',
                        innerHTML: "window.dataLayer = window.dataLayer || [];\r\nwindow.dataLayer.push({'gtm.start': new Date().getTime(), event: 'gtm.js'});"
                    },
                    {
                        src: `https://www.googletagmanager.com/gtm.js?id=${process.env.GTM_ID}`,
                        type: 'text/javascript',
                        async: true,
                    },
                    // Onetrust
                    {
                        src: `https://cdn.cookielaw.org/consent/${process.env.ONETRUST_ID}/otSDKStub.js`,
                        type: 'text/javascript',
                        'data-domain-script': process.env.ONETRUST_ID,
                    },
                    {
                        type: 'text/javascript',
                        innerHTML: 'function OptanonWrapper() { }'
                    }
                ] : [])
            ],
        }
    },

    security: {
        enabled: process.env.NODE_ENV === 'production',
        ssg: {
            meta: true, // Enables CSP as a meta tag in SSG mode<
            hashScripts: true, // Enables CSP hash support for scripts in SSG mode
            hashStyles: false // Disables CSP hash support for styles in SSG mode (recommended)
        },
        sri: true,
        nonce: true,
        headers: {
            crossOriginResourcePolicy: false,
            crossOriginOpenerPolicy: false,
            crossOriginEmbedderPolicy: false,// process.env.NODE_ENV === 'development' ? 'unsafe-none' : 'require-corp',
            contentSecurityPolicy: {
                'default-src': [
                    "'self'",
                    "'strict-dynamic'",
                    "'unsafe-inline'",
                    "'nonce-{{nonce}}'",
                    "'unsafe-eval'",
                    'https://*.ctfassets.net',
                    'https://*.contentful.com',
                    'use.typekit.net',
                    'https://*.googletagmanager.com',
                    'https://tagmanager.google.com',
                    'https://*.google-analytics.com',
                    'https://*.analytics.google.com',
                    'https://ssl.gstatic.com',
                    'https://www.gstatic.com',
                    'https://fonts.googleapis.com',
                    'https://cdn.cookielaw.org',
                    'https://geolocation.onetrust.com',
                ],
                'script-src-elem': [
                    "'self'",
                    "'strict-dynamic'",
                    "'nonce-{{nonce}}'",
                    'https://*.ctfassets.net',
                    'https://*.contentful.com',
                    'https://*.googletagmanager.com',
                ],
                'frame-ancestors': [
                    "'self'",
                    'https://app.contentful.com'
                ],
                'font-src': [
                    "'self'",
                    "'nonce-{{nonce}}'",
                    'data://*',
                    'use.typekit.net',
                    'fonts.gstatic.com',
                    'https://fonts.googleapis.com',
                ],
                'upgrade-insecure-requests': true,
                'img-src': false,
                'script-src': false,
            }
        },
    },
})
@BnitoBzh BnitoBzh added the bug Something isn't working label Apr 17, 2024
@vejja
Copy link
Collaborator

vejja commented Apr 17, 2024

Hi @BnitoBzh

There are many small things that you should double-check in your configuration. For instance font-src is not nonceable, setting CSP via script-src-elem instead of script-src is likely to block some script-src-attr, and setting open values to default-src is generally not recommended. Also you are loading the GTM script both via modules and via app.head unless I'm mistaken. There might be good reasons for all of these but just wanted to flag these first.

Aside from these, and in order to keep issues separate, can you do the following:

  • keep the default settings for contentSecurityPolicy
  • load GTM only via modules, i.e. erase the app.head entries
    And then let me know the CSP issue list with a screeshot if possible. This will help me better understand the situation. Thanks !

@vejja vejja added awaiting details Waiting for feedback from the issue author, i.e. reproduction and removed bug Something isn't working labels Apr 17, 2024
@BnitoBzh
Copy link
Author

@vejja, thanks for the CSP config issue I will make changes and test.
For the GTM script it must be loaded by the app.head in order to load it in the <head> section and not at the end of the <body> section. That is why the gtm.loadScript option is set to false, the nuxt-gtm module doesn't manage the script load.
In Chrome and Firefox everything works fine (although the empty nonce issue is still there), it doesn't just work on Safari.

@vejja
Copy link
Collaborator

vejja commented Apr 17, 2024

Could you let me know what you mean by 'empty nonce' ?
If your scripts are inserted by the client-side this is absolutely normal because only the server-side can insert nonces. But it shouldn't prevent your scripts from loading if you use strict-dynamic.

Please provide screenshots of the Safari complaints. Maybe the issue is due to how you manage the onload event handler, if required. Because your GTM script is inserted twice, it's hard to understand where the issue is coming from. I would first try to disable the module entry if it doesn't manage anything.

I can see that you are using Nuxt 3.11.2 : you could use the new useScript composable, which deals with all the hassle of loading external scripts.

@BnitoBzh
Copy link
Author

Here are two examples :
From the server response (with nonce)
from-server
From the dev toolbar, after load :
from-developer-tools

@vejja
Copy link
Collaborator

vejja commented Apr 17, 2024

The dev toolbar in the 'Elements' section does not display the nonce for security reasons
You can only see them in the raw server response in the Networks' Response tab

@BnitoBzh
Copy link
Author

Hum ok .. So do you have any idea why my CSP are ignored in Safari ?

@vejja
Copy link
Collaborator

vejja commented Apr 17, 2024

I can try to help if you send me a screenshot of the Console and Network Headers tabs of the Safari devtools

@Baroshem
Copy link
Owner

@BnitoBzh any details from your side? :)

@BnitoBzh
Copy link
Author

I have removed all nonce configurations and I use the forced declarations instead.

@vejja
Copy link
Collaborator

vejja commented Apr 23, 2024

@BnitoBzh I think this might actually be related to #432
I can see that you have { 'script-src': false, 'img-src': false } and another user reported that setting boolean values to CSP directives erased the nonces from the headers.
If you don't use boolean values in contentSecurityPolicy, would it fix the problem ?

@vejja
Copy link
Collaborator

vejja commented Apr 26, 2024

Hi @BnitoBzh , we fixed #432 in today's release.
Would you be able to upgrade to 1.4.2 to check if it solves your issue also ?

@BnitoBzh
Copy link
Author

Sorry, not enough time to test it now, i will test it in the next week.

@Baroshem Baroshem added this to the 2.0.0 milestone May 6, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
awaiting details Waiting for feedback from the issue author, i.e. reproduction
Projects
None yet
Development

No branches or pull requests

3 participants