On June 25, 2024, security researchers at Sansec published findings that the polyfill.io domain, which served a popular JavaScript polyfill library used by over 100,000 websites, had been acquired by a Chinese company called Funnull and was being used to inject malicious code into websites that loaded the polyfill script from the CDN.
The attack was elegant in its simplicity. The attackers did not exploit a vulnerability. They did not compromise a build pipeline. They bought the domain and started serving malicious JavaScript to every website that included a <script> tag pointing to cdn.polyfill.io.
What Polyfill.io Was
Polyfill.io was a service created by the Financial Times' development team (and specifically by developer Andrew Betts) that automatically served JavaScript polyfills based on the requesting browser's User-Agent. Polyfills are code snippets that implement modern JavaScript features in older browsers. If a user visited a website using an old browser, polyfill.io would serve the necessary compatibility code. If the browser was modern, it would serve a minimal or empty response.
The service was widely used because it solved a real problem elegantly. Rather than bundling polyfills for every browser into your JavaScript bundle (increasing size for all users), you could include a single script tag pointing to polyfill.io and let the service handle browser detection.
At its peak, the cdn.polyfill.io domain was loaded by over 100,000 websites, including major sites operated by corporations, government agencies, and news organizations.
The Domain Transfer
In February 2024, the polyfill.io domain was acquired by a company called Funnull (also seen as "Funnull CDN"). Andrew Betts, the original creator, had previously warned about the risks and stated he had no involvement with the polyfill.io service since 2018. He urged website operators to stop using polyfill.io and noted that modern browsers no longer need most polyfills.
Despite these warnings, the vast majority of websites continued to load scripts from cdn.polyfill.io after the domain transfer. The JavaScript loaded from the domain continued to function normally for several months after the acquisition, building trust, or at least complacency, among the sites that depended on it.
The Malicious Payload
Beginning in June 2024, Sansec detected that the code served from cdn.polyfill.io had been modified to include malicious redirects. The injected code was designed to redirect mobile users to sports betting and adult content sites through affiliate links, generating revenue for the attackers.
The malicious code was sophisticated in its targeting and evasion:
- It only activated on mobile devices, avoiding desktop users who were more likely to have security researchers examining their traffic
- It used specific User-Agent checking to avoid serving malicious code to web crawlers and bots
- It added timing-based delays before activating, making it harder to detect through automated scanning
- It only triggered on certain page views, not every load, reducing the likelihood of detection
- It used multiple layers of URL encoding and obfuscation to hide the redirect destinations
The targeting was calculated to maximize revenue while minimizing detection. Mobile users are less likely to notice unexpected redirects, and security researchers typically analyze websites using desktop browsers or headless browsers with standard User-Agent strings.
The Response
The response to the polyfill.io compromise came from multiple directions:
Google began warning advertisers whose pages loaded scripts from polyfill.io, threatening to disapprove ads on affected pages. This was highly effective because it created direct financial consequences for website operators who did not remove the script.
Cloudflare and Fastly both launched alternative polyfill services that automatically rewrote requests for cdn.polyfill.io to their own safe mirrors. Cloudflare's service, accessible at cdnjs.cloudflare.com, served the original, unmodified polyfill code.
Namecheap, the domain registrar, eventually suspended the polyfill.io domain. However, the attackers had already set up alternative domains to serve the same malicious payload, and some websites had been modified to point to these new domains.
Web security scanners and browser extensions were updated to flag pages that loaded scripts from polyfill.io.
The Fundamental Problem
The polyfill.io attack exposed a fundamental problem with how the web uses third-party JavaScript. When you include a <script> tag that loads code from an external domain, you are giving the operator of that domain complete control over your website for every visitor who loads that page. The external script runs with the same privileges as your own code. It can read form data, steal cookies, redirect users, modify page content, and exfiltrate data.
This trust is implicit and often invisible. Developers add a script tag during initial development, and it persists in the codebase for years, long after anyone has evaluated the security of the third-party service.
The polyfill.io case is particularly stark because the trust was placed in a domain, not even a specific piece of code. When the domain changed hands, the trust relationship was silently transferred to an entirely different entity with entirely different intentions.
Mitigation Strategies
Several technical measures can reduce the risk of this type of attack:
Subresource Integrity (SRI) allows you to specify a cryptographic hash of the expected script content. If the script changes, the browser refuses to execute it. However, SRI does not work well with services like polyfill.io that dynamically generate content based on the User-Agent.
Self-hosting third-party libraries eliminates the risk of domain takeover entirely. If you bundle the polyfill code with your own assets, a domain change does not affect you.
Content Security Policy (CSP) headers can restrict which domains your page loads scripts from. While CSP does not prevent the script from being malicious, it limits the attack surface by preventing the script from loading additional resources from unexpected domains.
Regular auditing of third-party script inclusions should be part of every web application's security program. Knowing what external domains your pages depend on is the first step toward managing the risk.
How Safeguard.sh Helps
Safeguard.sh extends supply chain visibility beyond traditional package dependencies to include the full spectrum of third-party components your applications rely on. Our SBOM tracking helps you inventory not just npm packages and library dependencies, but all external resources your applications load. When a third-party resource like polyfill.io is compromised, Safeguard.sh helps you identify every application in your portfolio that depends on it, enabling rapid remediation across your entire web presence. Our continuous monitoring approach means that changes in your dependency landscape, including domain transfers and ownership changes, are tracked and flagged before they become security incidents.