Every time your site loads a script from a CDN, you are trusting that CDN to serve exactly the code you expect. If the CDN is compromised, or if an attacker performs a man-in-the-middle attack, the script that arrives in your user's browser could be anything. A cryptocurrency miner. A credential harvester. A redirect to a phishing page.
Subresource Integrity (SRI) is the browser's built-in defense against this. You add an integrity attribute to your script or link tag containing a cryptographic hash of the expected file. The browser downloads the file, computes its hash, and compares. If the hashes do not match, the browser refuses to execute the file. Simple, effective, and almost nobody uses it.
The supply chain problem
In 2018, the event-stream npm package was compromised and a cryptocurrency-stealing payload was injected into a library used by thousands of applications. In 2019, a Magecart group compromised a CDN serving JavaScript to hundreds of e-commerce sites, injecting credit card skimming code. In 2021, the ua-parser-js npm package was hijacked and used to install crypto miners.
These are not theoretical attacks. They are documented incidents where third-party code, served from infrastructure the site owner trusted, was modified to attack the site's users. SRI would have prevented the browser from executing the modified code in every case where the script was loaded via a CDN.
How SRI works
You generate a SHA-384 or SHA-512 hash of the exact file you want to load:
sha384-oqVuAfXRKap7fdgcCY5uykM6+R9GqQ8K/uxy9rx7HNQlGYl1kPzQho1wx4JwY8wC
You add this hash to the script tag:
<script src="https://cdn.example.com/lib.js"
integrity="sha384-oqVuAfXR..."
crossorigin="anonymous"></script>
If the file on the CDN changes by even a single byte, the hash will not match and the browser will block execution. The crossorigin="anonymous" attribute is required so the browser can access the response for hashing.
What the audit checks
The Subresource Integrity Audit scans your page for every external script and stylesheet loaded from a third-party origin. For each one, it checks whether an integrity attribute is present and whether the hash algorithm is strong enough (SHA-384 or SHA-512, not the weaker SHA-256).
The tool also identifies scripts that are SRI-hostile. Some CDN-hosted scripts, like Google Tag Manager or Stripe.js, change their content on every request. Adding SRI to these would break them because the hash would never match. The audit recognizes these patterns and exempts them, so you know which scripts can and should have SRI and which ones cannot.
Why adoption is low
The main reason SRI adoption is low is that it adds friction to updates. When you update a library version, you need to update the hash too. If you forget, the site breaks. For teams that deploy frequently and use many third-party scripts, maintaining hashes feels like overhead.
But the alternative is silently trusting every CDN you depend on, every day, forever. And the fix is simple: generate the hash at build time. Every modern build tool can do this. If you are using a static site generator, add a post-build step that computes SRI hashes for all CDN-hosted resources.
For sites that load scripts from CDNs they do not control, SRI is the minimum viable defense. If you are building lean web properties and controlling costs, as I wrote about in The $100 Network, the security of your visitors is a cost you cannot afford to skip.
Fact-check notes and sources
- event-stream npm compromise: November 2018. Source: Snyk blog, "A post-mortem of the malicious event-stream backdoor."
- Magecart CDN-based attacks: multiple incidents 2018-2019. Source: RiskIQ research reports on Magecart groups.
- ua-parser-js hijack: October 2021. Source: GitHub Security Advisory GHSA-pjwm-rvh2-c87w.
- SRI is a W3C Recommendation (June 2016). Source: w3.org/TR/SRI/.
- SHA-256 is technically supported for SRI but SHA-384 is the recommended minimum. Source: MDN Web Docs, Subresource Integrity.
Related reading
- Remote dependency audit — finding all your external dependencies
- CSP strictness audit — another layer of script execution control
- Trusted Types for DOM XSS prevention — preventing injection at the DOM sink level
- API secret leakage audit — another supply chain risk surface
This post is informational, not security consulting advice. Mentions of Google, Stripe, and npm are nominative fair use. No affiliation is implied.