BIPI
BIPI

Polyfill.io and the Death of 'Just Use a CDN'

Cybersecurity

In June 2024 the Polyfill.io domain was caught serving malicious code to about 100,000 websites. The polyfill was fine. The CDN had changed hands and the new owner shipped whatever they wanted. The full story is the failure mode in one example.

By Arjun Raghavan, Security & Systems Lead, BIPI · March 18, 2025 · 7 min read

#supply-chain#cdn#third-party-scripts#javascript

In June 2024 a researcher noticed that polyfill.io — a popular CDN for JavaScript polyfills, used by roughly 100,000 websites including some surprisingly large names — was serving obfuscated code that redirected mobile visitors to fake gambling and adult sites. The polyfill itself was fine. The CDN it lived on had changed hands months earlier, and the new owner could ship whatever they wanted to every site that linked the script.

Every site that included <script src='https://polyfill.io/v3/polyfill.min.js'> was now running attacker-controlled JavaScript on every page load. The original polyfill code remained; the malicious payload was a small additional bundle, gated by user-agent so it only fired on mobile browsers, which delayed detection by weeks. Sites caught it eventually. Many did not.

How a benign CDN becomes a payload delivery system

Polyfill.io was originally maintained by an individual, Andrew Betts, who built it as an OSS project to ship browser polyfills based on the requesting User-Agent. Useful and popular. In 2024 Andrew sold the polyfill.io domain to Funnull, a Chinese-Singapore company with a documented history of suspicious behaviour around acquired domains.

Andrew himself publicly warned customers to migrate. Several CDN providers — Cloudflare, Fastly — removed polyfill.io from their default infrastructure. The warning was clear. Most consumers of the script never noticed. They had added the <script> tag years ago and never revisited it.

Funnull added the malicious payload some weeks after taking over the domain. The original polyfill bundle still loaded, so most sites continued to function normally. The attacker was patient: they only fired the redirect on specific mobile browsers and only some percentage of the time, which kept the signal-to-noise ratio low enough that most operators did not see the redirect in their analytics. By the time the security community caught it, the payload had been live for weeks.

Why CDN supply chain is uniquely dangerous

An npm package that is poisoned ships in your next deploy. You can roll back. A CDN script ships every time the user loads the page. There is no rollback because there is no version. The script changes when the CDN says it does. You do not need to redeploy; the attacker pushes to your users in real time.

Worse: most teams cannot list every third-party script their site loads. Analytics, A/B testing, marketing tags, chat widgets, consent banners, fonts, polyfills, payment SDKs. Each one is an attacker-shaped hole. The Polyfill.io attack is a single example of a structural problem.

100K+
Sites affected by Polyfill.io
weeks
Detection delay
0
Redeploys needed by the attacker

The audit we run

Step one is the inventory. Use a real browser DevTools session, load every page type, log every external script source. Most teams discover they have 20 to 40 distinct third-party origins running JavaScript on their site. The list is always longer than the team expects.

Step two is the ownership check. For each origin, look up the WHOIS, identify the operating company, check if it has changed hands recently. Domains that have transferred in the last 24 months are a yellow flag. Domains that transferred to companies with no public footprint are a red flag.

Step three is the necessity check. For each script, ask: do we still need this? Polyfills for IE11 are unnecessary in 2026. Marketing tags from a campaign that ended two years ago are dead weight. Removing scripts is the only fully durable defence; everything else is mitigation.

What SRI fixes (and does not)

Subresource Integrity (SRI) is a browser feature that checks the cryptographic hash of a fetched resource before executing it. <script src='...' integrity='sha384-...'> means: only execute this script if its bytes match this hash. If the CDN serves anything else, the browser refuses.

SRI works perfectly when you pin a specific file with a specific hash. It does NOT work for most polyfill.io and analytics setups, because those CDNs serve dynamic content based on User-Agent, time of day, A/B test allocation, and feature flags. The hash changes constantly by design. SRI cannot apply.

For libraries that ship as static files (lodash, moment, etc.) SRI is a strong defence. Pin to a specific version, generate the hash, add it to the script tag. The browser enforces.

The control we recommend installing

A CSP (Content Security Policy) header that restricts script-src to a known list of origins, paired with a reporting endpoint. Any new script origin appearing on the page triggers a CSP report; you see it in your SIEM the first time it loads. This catches drift — an attacker who poisons one of your existing CDN origins still passes script-src, but a new origin (which is most of how polyfill-style attacks chain) gets caught.

Closing

The 'just use a CDN' default is dead in any post-2024 threat model. Every third-party origin on your page is an attacker delivery channel that the attacker does not need your cooperation to use. Inventory them. Remove what you do not need. Self-host what you do. SRI-pin what you can. Run a script-src CSP and watch the report stream. The defences are not hard. The discipline of running them quarterly is.

Read more field notes, explore our services, or get in touch at info@bipi.in. Privacy Policy · Terms.