Nonce attributes values are erased during application boot - SSR mode
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,
}
},
},
})
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 theapp.headentries And then let me know the CSP issue list with a screeshot if possible. This will help me better understand the situation. Thanks !
@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.
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.
Here are two examples :
From the server response (with nonce)
From the dev toolbar, after load :
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
Hum ok .. So do you have any idea why my CSP are ignored in Safari ?
I can try to help if you send me a screenshot of the Console and Network Headers tabs of the Safari devtools
@BnitoBzh any details from your side? :)
I have removed all nonce configurations and I use the forced declarations instead.
@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 ?
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 ?
Sorry, not enough time to test it now, i will test it in the next week.
Closing the ticket as the issue was resolved. If there is a need to reopen, please let me know :)