Breach report
polyfill.io: how one bought domain poisoned 100,000+ websites overnight
What happened
polyfill.io was a widely used free service that supplied JavaScript "polyfills" — small compatibility shims — to hundreds of thousands of websites via a simple <script> tag. In early 2024 the domain and its associated GitHub project were acquired by a new operator (reported by Sansec as the Chinese company Funnull). By June 2024, cdn.polyfill.io began serving malicious JavaScript, with Sansec initially reporting more than 100,000 affected sites and later analyses citing figures in the hundreds of thousands. The injected code redirected mobile users to scam and betting sites and employed anti-analysis techniques to evade detection.
Every site that trusted the CDN was, in effect, serving the attacker's code to its own visitors — without changing a line of their own code.
Root cause
The affected sites loaded third-party JavaScript directly from a domain they did not control, with no integrity verification. When the domain changed hands, the implicit trust transferred to whoever now controlled it. This is the archetypal software supply-chain failure, and it is why OWASP added Software Supply Chain Failures as a new category (A03) in its 2025 Top 10.
How it would have been caught
Software Composition Analysis and a CI check that flags any external <script> include lacking a Subresource Integrity (SRI) hash would have surfaced the exposure. Domain- and dependency-monitoring that alerts on ownership changes would have flagged the acquisition itself. The audit is simple: inventory every externally hosted asset and confirm each is either self-hosted or pinned by hash.
How to prevent it
- Self-host critical third-party scripts, or pin them with Subresource Integrity hashes so any change to the file causes it to fail to load rather than execute.
- Constrain script sources with a Content-Security-Policy allowlist.
- Adopt build-input provenance (SLSA) and treat every external dependency and CDN as an untrusted control sphere.
The Breachwire test (red → green)
Serve a modified version of an externally included script and confirm the page executes it (the vector is real). Add an SRI hash, then confirm the tampered file fails to load while the correct, pinned version still loads — proving the browser now rejects any substitution.