Safeguard
Incident Analysis

Polyfill.io supply chain attack

How a domain sale turned a trusted CDN into a malware vector for 100,000+ sites — and what the polyfill.io incident teaches defenders about third-party script risk.

Safeguard Research Team
Research
7 min read

June 25, 2024 — Domain registrars, CDNs, and browser vendors moved within hours to blacklist a single line of code that an estimated 100,000+ websites had trusted for years. That was the day security research firm Sansec disclosed that polyfill.io — a widely used, free CDN that served JavaScript compatibility shims to older browsers — had been quietly weaponized to inject malware into visitors on mobile devices. The domain had changed hands in February 2024, and within four months the free open-source utility that once helped Internet Explorer users render modern websites had become a live malware-distribution channel embedded in the source code of major consumer brands, media outlets, and e-commerce platforms.

The incident is now one of the most cited case studies in software supply chain security — not because the exploit itself was technically exotic, but because it exposed how much of the modern web still runs on implicit trust in third-party-hosted code that nobody re-audits after the initial integration.

What Happened

Polyfill.io began life as an open-source project maintained by Financial Times engineer Andrew Betts, providing "polyfills" — small shims that backfill missing JavaScript features in older browsers — via a free, cacheable CDN endpoint (cdn.polyfill.io). Because it solved a genuinely useful cross-browser compatibility problem, sites embedded a single <script src="https://polyfill.io/v3/polyfill.min.js"> tag and moved on, often never touching that line of code again.

In February 2024, Betts sold both the GitHub organization and the domain to a company operating under the name Funnull, a firm security researchers had already linked to malicious CDN infrastructure and scam-adjacent redirect networks. Betts later publicly warned users to remove the script immediately, stating he had no ongoing relationship with the acquirer and had not vetted their intentions.

By June, that warning proved prescient. Sansec's research showed the domain had started dynamically serving malicious payloads to specific site visitors — conditionally, and only under circumstances designed to minimize the chance of detection by automated scanners or site administrators.

The Attack Mechanism

What made the polyfill.io compromise notable from a defensive-engineering standpoint was its evasion logic, not its payload sophistication. The injected script:

  • Targeted mobile devices specifically, based on User-Agent string inspection, reducing the chance that a security team testing from a desktop browser would ever see the malicious behavior.
  • Excluded administrative and logged-in sessions, which meant site owners auditing their own properties from an authenticated admin view were unlikely to trigger the payload.
  • Delayed and conditionally activated, executing only for a subset of requests and time windows, a common technique to frustrate crawlers and scanning tools that expect consistent, reproducible behavior.
  • Redirected victims to sports betting platforms and fraudulent sites, including domains impersonating Google Analytics (such as typosquats like www.googie-anaiytics.com), a pattern consistent with traffic-monetization and credential-phishing campaigns rather than a targeted espionage operation.

Because the payload was served from a domain that had been embedded directly in site source for years, none of this required a code change on the victim's end, no pull request, no dependency bump, no npm install. The compromise lived entirely upstream, in infrastructure the affected organizations did not control and, in most cases, had stopped thinking about entirely.

Scope and Impact

Estimates of exposure varied by methodology, but multiple scanning efforts converged on a consistent picture: over 100,000 sites referenced the polyfill.io script at the time of disclosure, spanning e-commerce storefronts, media properties, SaaS marketing sites, and — notably — subdomains or marketing pages belonging to large, recognizable consumer brands that had no reason to expect a compatibility shim would become an attack vector.

The exposure was compounded by a structural feature of CDN-hosted scripts: many of the affected sites had never pinned a specific version or subresource-integrity (SRI) hash, meaning the script tag would continue fetching and executing whatever the domain owner chose to serve, indefinitely, with zero visibility into changes on the vendor side.

Industry Response

The response moved fast, largely because the fix didn't require patching code inside any individual organization — it required cutting off the domain.

  • Cloudflare and Fastly both stood up automatic URL rewriting, transparently redirecting requests for polyfill.io scripts to safe, functionally equivalent mirrors (in several cases, hosted via cdnjs) without requiring customers to touch their own markup.
  • Namecheap, the domain's registrar, suspended polyfill.io following abuse reports.
  • Google began flagging and blocking ads for sites that still referenced the compromised script, adding a monetization incentive on top of the security one.
  • GitHub removed the Polyfill organization and associated repositories tied to the acquirer.
  • Security vendors and CDNs published detection guidance en masse, largely converging on a single, simple recommendation: remove the script tag entirely, since virtually all the polyfills it served are unnecessary for the current baseline of supported browsers.

Within roughly a week, the practical exposure for organizations that acted on the guidance had dropped substantially — but the incident left a longer tail of unpatched sites that either never noticed the disclosure or lacked an inventory precise enough to know they were affected in the first place.

Why This Matters: The Third-Party Script Supply Chain

Polyfill.io is a clean illustration of a supply chain risk category that gets less attention than package-registry attacks (npm, PyPI) but is arguably more invisible: externally hosted, runtime-loaded JavaScript that executes with the full privileges of the page it's embedded in. Unlike a compromised npm package, which at least shows up in a lockfile diff or a dependency-scanning alert, a CDN-hosted script tag has no build-time signal. The code that runs in production today can be entirely different from the code that ran yesterday, and most static SBOM and dependency-scanning tooling — built around package manifests — never sees it at all.

This is compounded by an ownership-transfer risk that is structurally similar to abandoned-package takeovers seen elsewhere in the ecosystem (maintainer account compromises, expired-package squatting, and transferred npm packages have all produced comparable incidents). When a domain, GitHub org, or package name changes hands, every downstream consumer inherits the new owner's intentions with zero notification and zero re-review, unless someone is actively watching for it.

The lesson security teams have drawn from polyfill.io is not "audit every third-party script once," but "treat externally-loaded runtime code as a continuously changing dependency" — something that needs the same reachability-aware, continuously monitored posture as an npm package, not a one-time inclusion decision made years ago and forgotten.

Lessons for Defenders

A few durable takeaways from the incident:

  1. Inventory beyond the manifest. SBOMs generated purely from package.json or lockfiles miss runtime-loaded, CDN-hosted scripts entirely. Any organization that can't answer "which of our sites load third-party JavaScript, from where, and pinned to what version" has a blind spot polyfill.io-style attacks live in.
  2. Subresource Integrity (SRI) is cheap insurance. A script tag with an SRI hash fails closed if the upstream content changes unexpectedly — turning a silent compromise into a loud, visible break.
  3. Ownership changes are a signal, not noise. Domain transfers, maintainer handoffs, and org acquisitions on projects you depend on deserve the same scrutiny as a new CVE.
  4. Evasive payloads are the norm, not the exception. Attackers increasingly design malicious code to dodge automated scanners and administrative sessions specifically because they know defenders test from privileged, non-representative vantage points.

How Safeguard Helps

Safeguard is built for exactly this class of blind spot. Our SBOM generation and ingestion pipeline extends beyond package manifests to catalog third-party and CDN-hosted script dependencies across an organization's web properties, so a domain-ownership change like the one behind polyfill.io shows up as a tracked, alertable event rather than a silent runtime shift. Griffin AI continuously correlates emerging threat intelligence — including CDN and dependency ownership transfers, newly disclosed malicious infrastructure, and abuse reports — against your actual asset inventory, surfacing exposure before a vendor disclosure forces a scramble. Our reachability analysis distinguishes between a script that's merely referenced somewhere in your codebase and one that's actually loaded and executed in production paths reachable by real users, cutting through the noise so teams triage the polyfill.io-style incidents that matter to their specific deployment first. And where remediation is straightforward — swapping a compromised CDN reference for a vetted mirror, pinning a version, or adding SRI hashes — Safeguard's auto-fix PRs deliver the change directly into your workflow, turning a multi-day incident response scramble into a reviewed, mergeable pull request.

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.