Reputation: 186
I have a Vue application that uses SSR. In order to implement Content-Security-Policy, I use nonce-aware version of GTM snippet.
But it was not adding the nonce
to all scripts that get injected by gtm to the page (specifically Custom HTML tags). I followed the solution mentioned here and it fixed the issue on Safari. But it doesn't work on Chrome, Firefox, or Edge and I still see the error for those tags:
this is my CSP settings:
default-src 'self';
base-uri 'self';
block-all-mixed-content;
font-src 'self' https: https://fonts.gstatic.com data:;
img-src 'self' https: data: https://www.google-analytics.com https://ssl.gstatic.com https://www.gstatic.com https://www.googletagmanager.com;
object-src 'none';
script-src 'self' 'nonce-b62382357618aee340fc9dc596c94a19' https://www.google-analytics.com/ https://ssl.google-analytics.com https://tagmanager.google.com https://www.googletagmanager.com 127.0.0.1:*;
script-src-attr 'none';
style-src 'self' 'unsafe-inline' https://tagmanager.google.com https://fonts.googleapis.com;
upgrade-insecure-requests;
connect-src 'self' https://www.google-analytics.com https://stats.g.doubleclick.net;
After hours and hours of research I found the following comment:
Chrome masks the nonce attribute value so tag manager is unable to grab it and store it as a variable.
I am not sure if this is really the issue but can anyone please explain how I can tackle this issue without using unsafe-inline
or hashes as it seems there is no standard way of fixing it even on Google documentations?
Upvotes: 4
Views: 3396
Reputation: 186
After searching a lot on the internet and reading different articles, I found out the solution mentioned here works perfectly well in Safari but not in other browsers because:
Chrome, Safari, and Edge mask the nonce attribute value so GTM is unable to grab it and store it as a variable.
Considering this solution for propagating the nonce
to the custom HTML tags, we go ahead and apply the following changes to fix this issue on Chrome, Firefox, and Edge.
As suggested here in the comments we need to modify the nonce-aware script a little bit and put the nonce in a data-
attribute (then the browsers won't mask it), and push it to the dataLayer:
<!-- Google Tag Manager -->
<script
nonce='{{YOUR_GTM_NONCE}}'
data-gtm-nonce='{{YOUR_GTM_NONCE}}'
>
(function(w,d,s,l,i){
const gtmNonce = d.querySelector('[data-gtm-nonce]').dataset.gtmNonce;
w[l]=w[l]||[];
w[l].push({'nonce': gtmNonce});
w[l].push({'gtm.start': new Date().getTime(),event:'gtm.js'});
const f=d.getElementsByTagName(s)[0],j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';
j.async=true;
j.src='https://www.googletagmanager.com/gtm.js?id='+i+dl;
j.setAttribute('nonce', gtmNonce);
f.parentNode.insertBefore(j,f);
})(window,document,'script','dataLayer','YOUR_GTM_ID');
</script>
<!-- End Google Tag Manager -->
Then in the GTM, you need to change the nonce variable you defined based on this solution from this:
The rest will be kept the same.
Upvotes: 1