Here is the whole attack in one sentence: in February 2024, a company bought a domain.

That’s it. Nobody breached a server. No credential was phished, no CVE was exploited, no build pipeline was poisoned. Somebody paid money for polyfill.io, a domain that more than a hundred thousand websites had been pointing a <script> tag at for years, and acquired — legally, in a transaction — the right to run arbitrary JavaScript in all of their visitors’ browsers. Four months later, they used it.

What polyfill.io was, and why everyone trusted it

A polyfill is a small piece of JavaScript that teaches an old browser a feature it’s missing — a fetch() here, an Array.flat() there. The polyfill.io service, originally built by Andrew Betts while he was at the Financial Times, did something clever with that: you put one script tag on your page, and the service looked at each visitor’s User-Agent and sent back exactly the polyfills that particular browser needed. A modern Chrome got an almost-empty file. An ancient browser got a pile of shims. One URL, a custom response per request.

It was genuinely useful, it was free, and so it spread. By 2024 it was embedded in everything from hobby blogs to government sites to the checkout pages of real stores. The script tag was copy-pasted into templates a decade ago and forgotten, which is exactly how third-party dependencies become load-bearing: not by decision, by accumulation.

And every one of those tags was an instruction to the browser that read, in effect: fetch code from this domain and execute it with full privileges on my page, every time anyone visits. That’s not hyperbole about what a script tag does. That is literally what a script tag does.

The design that made it impossible to defend

Here’s the part that turns this from “another supply-chain story” into something worth sitting with. The web already has a defense for exactly this threat. It’s called Subresource Integrity, and it lets you pin a cryptographic hash to a script tag: integrity="sha384-...". The browser downloads the script, hashes it, and refuses to run it if the hash doesn’t match. If you SRI-pin a third-party script, the provider can’t change it on you — any change breaks the hash and the browser blocks it.

You could not use SRI with polyfill.io. Not because people forgot to, but because the service’s whole selling point made it impossible: the response was different for every browser. There is no single hash to pin when the bytes are generated fresh per request. The feature that made polyfill.io convenient — dynamic, per-visitor responses — was the exact feature that disabled the one browser mechanism designed to stop a CDN from going rogue.

So a hundred thousand sites were running unpinnable, unverifiable, remotely-controlled code from a domain, and the only thing standing between them and catastrophe was who happened to own the domain. Trust was doing all the work, and trust was for sale.

February: the warning nobody acted on

The ownership change wasn’t a secret, and this is the part that should bother anyone in this field. When the domain and the project’s GitHub account were sold to a Chinese company in February 2024 — one later tied to the CDN operator Funnull — Andrew Betts — the person who built the thing — went public immediately. His message was blunt: he had never owned the domain, he had no say in the sale, and if your site includes cdn.polyfill.io, you should remove it right now. Modern browsers, he pointed out, don’t even need polyfills anymore.

Every signal was there, in the open, months before any malware shipped. The WHOIS/RDAP record changed hands. The GitHub account changed hands. The original author stood up and said stop trusting this. None of it required a security team or a scanner to notice — it required someone to be watching the provenance of the code their site depended on. Almost nobody was. The script tag had been invisible infrastructure for ten years; nobody was assigned to watch it, because nobody remembered it was there.

June: the bill came due

On June 25, 2024, researchers at Sansec reported that cdn.polyfill.io was injecting malicious code into the sites that embedded it. The payload was careful in the way that tells you this was a professional operation, not a smash-and-grab. It was generated dynamically based on the request headers, so a researcher pulling the file with curl saw something different from a phone on a mobile network. It targeted mobile devices and activated only at certain hours. It stayed quiet when it detected an admin user, and when it found a web analytics service it delayed itself — presumably, Sansec noted, to stay out of the stats. It also carried anti-reverse-engineering tricks.

When it did fire, it redirected victims through a fake analytics domain — www.googie-anaiytics.com, a typo-squat of Google’s that’s easy to miss in a log — onward to a sports betting site. The initial count was “over 100,000 sites.” A sweep by Censys on July 2 still found 384,773 hosts embedding a script that referenced the domain.

The cleanup was fast and told its own story about how much of the web runs through a few intermediaries. Google started blocking ads for e-commerce sites that loaded the script. Cloudflare began rewriting requests for cdn.polyfill.io, in real time, on every site behind its network, swapping in a safe mirror. Fastly stood up a clean copy at a different domain. Namecheap, the registrar, put the malicious domain on hold within days. The attack was ended not by the hundred thousand site owners — most of whom never knew — but by a handful of infrastructure companies with the reach to override a script tag at the edge.

The lesson is about ownership, not code

It’s tempting to file this under “audit your dependencies,” but that framing misses the specific thing that happened. The code wasn’t the vulnerability. The code was fine for years. The vulnerability was that the right to change the code was an asset that could be bought, and the people depending on it had no mechanism — technical or organizational — to notice when it was.

A <script src> pointing at a domain you don’t control is not a dependency in the way a pinned library version is a dependency. It’s a standing delegation of code execution, renewed on every page load, revocable by whoever holds the domain, and silently transferable with the deed. You are trusting not a piece of code but a continuing relationship with whoever answers that hostname — and domains, unlike code, change owners quietly and legally all the time.

The defenses that actually address this are unglamorous. Self-host the third-party scripts you can, so a sale somewhere else can’t reach into your users’ browsers. Pin with SRI wherever the provider serves static bytes, and treat “we can’t pin this because it’s dynamic” as the loud warning it is, not a shrug. And — this is the part the industry is worst at — keep an eye on the provenance of what you depend on: who owns the domains in your script tags, and whether that answer is still the one you signed up for. The polyfill attack didn’t need a zero-day. It needed everyone to stop paying attention for ten years, which is a much more reliable exploit.