On June 25, 2024, security firm Sansec disclosed that polyfill.io — a JavaScript CDN embedded on more than 100,000 websites — had been quietly serving malware after its domain and GitHub account were sold to a company called Funnull. Visitors on mobile devices were silently redirected to sports betting and adult-content sites, and the payload was built to detect and evade security researchers. The attack worked because the vast majority of those 100,000+ sites loaded the polyfill.io script without a Subresource Integrity (SRI) hash, so browsers had no way to verify the file hadn't changed since the developer first linked to it. SRI exists to prevent exactly this: a cryptographic hash on a <script> or <link> tag that tells the browser to refuse a resource if its bytes don't match. But SRI is not automatic, not universal, and not immune to the same supply chain compromises it was designed to stop. Here's where it actually breaks down.
What is Subresource Integrity, and what does it actually check?
Subresource Integrity is a W3C browser standard that lets a page attach a base64-encoded SHA-256, SHA-384, or SHA-512 hash to a <script> or <link> tag so the browser verifies the fetched file's contents against that hash before executing or applying it. If the hash doesn't match, the browser blocks the resource entirely and logs a console error — it fails closed, not open. The spec reached W3C Recommendation status in June 2016 and has shipped in Chrome since version 45 (2015) and Firefox since version 43, so support across evergreen browsers has been universal for close to a decade.
The catch is that SRI only checks integrity in transit between the CDN edge and the browser at fetch time. It requires the crossorigin attribute for cross-origin resources because the check depends on a CORS-enabled response, and it only covers elements that explicitly declare it — <script src>, <link rel="stylesheet">, <link rel="preload">, and <link rel="modulepreload">. Nothing forces a developer to add the attribute, and nothing re-verifies the file after the hash was generated if the source artifact was already compromised before anyone computed the hash.
How does an SRI bypass actually work?
An SRI bypass almost never involves breaking SHA-384; it involves finding the places SRI was never asked to look. Four patterns account for nearly every real-world case:
- No integrity attribute at all. This is the dominant failure mode — a
<script src="https://cdn.example.com/lib.js">tag with nointegrityvalue has zero protection, and third-party CDN snippets copy-pasted from vendor documentation routinely ship without one, exactly as polyfill.io's embedders did. - Dynamically injected resources. Scripts created at runtime via
document.createElement('script'), loaded throughfetch()andeval(), or pulled in viaimport()bypass the declarativeintegrityattribute unless a developer manually fetches the file, hashes it, and checks it themselves — which almost never happens in practice. - Build-time hash poisoning. If an attacker compromises the source repository, build server, or npm package before the SRI hash is generated during CI, the malicious file matches its own hash perfectly. SRI verifies the file hasn't changed since the hash was made — it says nothing about whether the file was already backdoored when that happened.
- CORS/crossorigin misconfiguration. SRI checks depend on a CORS-compliant response; missing or misconfigured
crossoriginattributes on cross-origin tags can cause the browser to skip verification rather than block the load, silently disabling the protection developers believe is active.
What happened in the polyfill.io supply chain attack of 2024?
The polyfill.io attack turned a widely trusted CDN into a malware distribution channel for over 100,000 sites, and it happened because the service's ownership — not its code repository — changed hands. Andrew Betts, the original polyfill.io author, had already warned in February 2024 that he no longer controlled the domain after selling it, and by June, Sansec confirmed the CDN was injecting a redirect payload that specifically excluded admin users and delayed activation to dodge review. Cloudflare and Fastly responded by standing up free, auditable mirror CDNs (cdnjs.cloudflare.com polyfill mirror and Fastly's polyfill-io mirror) within days, and Namecheap suspended the polyfill.io domain entirely by late June 2024. Google went further, blocking Google Ads for advertiser sites that still referenced the compromised domain. Sites that had implemented SRI hashes against the original, trusted polyfill.io content were protected — the moment the served bytes changed, the hash mismatch blocked execution. Sites without SRI had no such backstop and ran the malicious code unknowingly.
Why did British Airways' 2018 Magecart breach slip past existing web defenses?
British Airways was breached because a third-party JavaScript library on its payment page was modified to skim card data, and no integrity check caught the change before 380,000 customer transactions were compromised. Between August 21 and September 5, 2018, attackers linked to the Magecart group altered a Modernizr JavaScript file served from BA's baggage-claim information page, adding roughly 22 lines of code that copied form field data — card numbers, expiry dates, CVVs, names, and addresses — and exfiltrated it to a look-alike domain, baways.com, registered specifically to blend in. The UK Information Commissioner's Office initially proposed a £183.39 million fine under GDPR and ultimately settled at £20 million in October 2020, one of the largest data protection penalties issued in the UK at the time. Had BA pinned that Modernizr script with an SRI hash, the altered file's mismatched hash would have caused browsers to refuse to run it — a single missing attribute on a single <script> tag was the difference between a blocked attack and a nine-figure incident.
Can SRI be bypassed even when the hash is correct and present?
Yes — a technically valid, correctly matching SRI hash offers no protection if the file was malicious before the hash was ever generated. This is the scenario that played out in the event-stream incident in November 2018, when a maintainer handed publishing rights for the popular event-stream npm package (roughly 2 million weekly downloads at the time) to an unknown contributor who added a malicious dependency, flatmap-stream, designed to steal cryptocurrency wallet credentials from the Copay Bitcoin wallet app. Anyone who computed an SRI or subresource hash against that published, backdoored file would have gotten a hash that matched perfectly and "verified" cleanly, because the compromise happened upstream of the hashing step, at the source. SRI protects the integrity of a specific byte sequence between two points in the delivery chain; it makes no claim about whether that byte sequence was trustworthy to begin with. That's why SRI adoption reduces one class of risk — CDN or edge tampering — while leaving source and build-pipeline compromise entirely untouched.
How Safeguard Helps
Safeguard treats SRI gaps and supply chain tampering as facets of the same reachability problem rather than isolated checklist items. Safeguard's SBOM generation and ingest pipeline continuously catalogs every third-party script, CDN dependency, and package your applications actually load in production, flagging assets that ship without integrity attributes or that reference domains with a history of ownership changes like polyfill.io's. Reachability analysis then determines whether a given script or package is genuinely invoked in a code path an attacker can reach, so security teams triage the handful of resources that matter instead of every CDN reference in the codebase. Griffin AI, Safeguard's agentic security analyst, correlates that reachability data against live threat intelligence — so when a CDN is later confirmed compromised, Griffin surfaces every affected asset within minutes rather than days of manual grep-and-hope. When gaps are found, Safeguard opens auto-fix pull requests that add the missing integrity and crossorigin attributes or pin dependencies to vetted, hash-locked versions, closing the loop from detection to remediation without waiting on a manual audit cycle.