Google Tag Manger script causing PCI-DSS compliance fail

An interesting issue this morning. A client contacted us because their site had failed its monthly PCI-DSS compliance scan. This is not normally an issue – most of the time it’s because the scan picks up only the headline version number of, say, Nginx or PHP, and believes that it’s out of date, without realising that the vulnerability it thinks exists has been fixed through backporting.

Not so this time. The sole point of failure was the inclusion of a script from a third party website without an SRI tag.

Scripts on a website, like pretty any resource, can be loaded either from the site’s own server, or from a third party website. This may be as part of a content delivery network, to speed up loading times, or – as in this case – the Google Tag Manager script which lets users use Google’s Tag Manager control panel to determine what’s loaded on the site, without having to make amendments

Loading a script from a third party without some form of checking, though, does represent a security vulnerability. What if the third party’s website has been hacked and the benign script has been replaced with something more malicious. And that’s where SRI tags come in to play.

SRI, or Sub-Resource Integrity, is a way of checking that the resource that is being retrieved from the third party website has been delivered without being manipulated in some way, by specifying a “hash” that the resource received must match.

Hashing is essentially using a mathematical function to generate a value that represents the contents of the file or text in question. So if we hash the preceding paragraph in this post, it gives us a value of “C4151375256F429DAF7E3D6FFDA2BF50234BF3D4” – this is unique, and if any part of the preceding paragraph were to be changed, then the hash value returned would be completed different. Strip out the final full stop and re-hash it, and the hash value becomes “F95639F3F300CCDC324737B3711E75278C3B4A40”.

So when including a third party resource, ideally we would include an SRI tag that specifies the hash that that resource should result in. When the resource is retrieved, it’s hashed, and if the hash matches, then we know that the resource is what it should be and hasn’t been tampered with.

The problem, in this instance, is that when including the Google Tag Manager script you are not pulling in a static piece of text. The whole point of the Tag Manager is to allow you, the end user, to easily adjust what metrics are measured, and to allow Google to update the script without having to get everyone using the script to update their websites to pull in the new version.

So when you use a script tag to call, for example, “https://www.googletagmanager.com/gtag/js?id=UA-123456789-1” what is actually being returned can change from time to time, either because the end user chooses to add or remove metrics to measure, or because Google has tweaked the script. So including an SRI tag is practically impossible, because the hash would almost certainly be out of date within a few days, and the resource would stop loading.

If this issue has flagged up on your PCI DSS scan, then it’s going to be a case of getting your scan company to accept that, which isn’t guaranteed to be an easy task because they are notorious for their box-ticking approaches. It may be worth arguing that it’s not a PCI DSS compliance issue – or that it’s a risk which you’re aware of but which does not impact on card payments. Ensure that access to your Google Tag Manager control panel is restricted to whoever needs access, and restrict them only to what they need access to, and protect all logins to it via two-factor authentication. But beyond that, there’s not necessarily a huge amount that you can do to satisfy the scan companies.

Given that it seems to be a relatively new issue arising, we will have to see how pragmatic their approach is.