Google Analytics and CSP

Thu, 2017-09-07 19:52

CSP or Content-Security-Policy is an HTTP header that instructs the user agent (your browser) about what resources the site intends the browser to use. This is an extremely helpful mechanism to prevent Cross Site Scripting attacks (or XSS). The point of this post is not to explain about CSP, because MDN has done an excellent job, but to explain how I adjusted my CSP settings to allow tame Google Analytics.

Disable Inline scripts

One super important feature in CSP is that you can prevent the browser from executing inline JavaScript. This is important because most XSS attacks are failures to sanitize user input, and become inline scripts. When you disable inline-scripts, you shrink the leeway of such attacks quite a lot. However, the default GA integration is to add an inline JavaScript. You'd have to allow inline JavaScript with a CSP like the following for this to work. It's a terrible way, and I highly recommend you to not do it like this:

Content-Security-Policy: script-src 'unsafe-inline';

Again, this is a terrible idea because you are throwing one major advantage of CSP right out of the window.

To overcome this, what I did was serving the script in a file (or rather append it to an existing file that already had some tracking in it).
So, the first step is to move the snippet that looks like the following into a new file or an existing file and serve it as a normal JavaScript file.

<script>
  (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[...
      ...
  ...cs.com/analytics.js','ga');
  ga('create', 'UA-111111111-1', 'auto');
  ga('send', 'pageview');
</script>

When you move your snippet into a separate file, there will be a small delay when your tracking script is added. This can skew your page load time statistics shown in Google Analytics, but this was a compromise I was willing to make.

Load delay caused by moving the analytics script to a separate file

Allow images and scripts from www.google-analytics.com

Now with the script moved to a separate file, you have to allow scripts from www.google-analytics.com in your pages. After the script is added, Google Analytics will kick in, and then try to run a beacon with an image, which means you have to allow images from the same domain, too.

Analytics without allowing image-src

With those two allowed, your CSP would look like this:

Content-Security-Policy: script-src www.google-analytics.com; img-src www.google-analytics.com

Now I hope you know that above is not your final CSP. The point is that you have allow script and images from www.google-analytics.com in order for this to work. The above is the relevant part of my recent CSP that allowed Google Analytics to run well, and I didn't have to allow inline scripts at all.

TL;DR

  • 📜 Move your inline Analytics script to a separate file
  • ✅ Allow scripts from www.google-analytics.com with script-src directive.
  • ✅ Allow images from www.google-analytics.com with img-src.
  • ➡️ Content-Security-Policy: script-src www.google-analytics.com; img-src www.google-analytics.com
  • ⚠️Take note that the above is not your final CSP.
  • GA 🤜🤛 CSP