What you need to know:
- On June 25, 2024, the cdn.polyfill.io domain started injecting malware into the popular polyfill.js library, estimated to be used by over 100,000 sites.
- On June 26, Cloudflare started automatically rewriting requests to cdn.polyfill.io and serving up their safe mirrored copy of the library.
- As of June 27, Invicti products include dedicated security checks to flag any use of polyfill.io in applications.
- The polyfill.io domain has been taken down (though it may still be cached) and there is no immediate risk of compromise, but all sites and applications that loaded scripts from polyfill.io should remove them as a precaution since the domain is now treated as malicious.
- A best practice to protect against similar attacks in the future is to use the Subresource Integrity (SRI) feature when loading external dependencies.
The action-packed story of polyfill.io
The open-source Polyfill project was created a decade ago as a convenient aggregation of polyfills for website and web application development. In February 2024, the polyfill.io domain was bought by a suspicious company named Funnull, most likely of Chinese origin. Subsequently, there were some reports of cdn.polyfill.io injecting malware when loaded on mobile devices, but any complaints were quickly deleted from the GitHub repository.
The full-scale supply chain attack was reported on June 25th, with cdn.polyfill.io injecting malicious code into websites that loaded scripts from this domain. Over 100,000 sites were found to be loading poisoned polyfills, serving up a variety of malware to browsers. Major providers such as Google and Cloudflare were quick to respond to mitigate the threat. Cloudflare, in particular, had long been suspicious of the new owners of polyfill.io and had created its own copy of the Polyfill repo. When the attacks started, Cloudflare started rewriting requests to cdn.polyfill.io to point at its own, safe mirror of the repo. Both Cloudflare and Fastly have been providing a safe mirror of Polyfill since February.
As of this writing, the polyfill.io domain has been taken down completely by its operator, eliminating the immediate risk of attack and buying time to remove any references to cdn.polyfill.io from applications that loaded scripts from that domain.
Polyfills are helper scripts (usually JavaScript loaded from a web source) that provide modern functionality for older browser versions that might not support a specific feature. They were a popular tool in the days of limited cross-browser compatibility but are much less useful with modern browsers that implement specifications in a more standardized way. The original creator of the Polyfill project has been discouraging the use of polyfills for several years now, saying they are unnecessary and potentially risky.
Another link in the web application supply chain
“The Polyfill incident serves as yet another illustration of how complex and vulnerable the web application security supply chain has become, particularly in the JavaScript ecosystem on the client side,” said Dan Murphy, Chief Architect at Invicti Security. “The difference here compared to similar high-profile attacks is that malicious actors simply took control of a widely-used project instead of quietly exploiting a vulnerability somewhere in the shaky pyramid of web dependencies.”
Many scripts are now loaded via content delivery networks for improved performance, making CDNs another link in the supply chain and thus a potential target. Without some way of checking if your dependency has been tampered with, you are effectively trusting the CDN operator with your application security.
Using Subresource Integrity to prevent the next Polyfill
Luckily, there is a clever browser feature that can save you in case of an attacker taking over the CDN of one of your dependencies: Subresource Integrity (SRI) checking. Most modern websites work with a very specific set of library versions and once a version has been imported, that’s the one you use, unless a new one is available and you decide to upgrade. It works the other way, too: once a version is published, it is generally not modified. If something needs changing, it’s normally put in a new version that you can use or ignore. In other words, once you have included the file in your application, it should never change—and if it does, there’s something weird going on.
Enter the Subresource Integrity browser feature that lets you ensure a resource hasn’t changed since you included it in your application. To use SRI, you need to create a hash (sha256, sha384, or sha512) of the file you’re loading, and online tools are available to do it automatically for you. You then simply put the hash in the integrity attribute of your script or link tag, as in this sha384 example for jQuery:
Once this is done, the resource will load as normal. If anything changes on the server side, however, like if malicious code is added, the stored hash will no longer match the hash of the incoming script or stylesheet and browsers will refuse to load the resource. This protects you not only from malicious tampering but also from CDN-side issues such as misconfigurations or switch-ups that may be hard to debug while impacting the functionality of your website.
Security checks in Invicti products to verify SRI and find Polyfill usage
Invicti products include checks to warn you when a site is not using Subresource Integrity (SRI not implemented at Best-practice severity or Informational severity for the Acunetix equivalent) or an existing SRI hash is wrong (SRI hash invalid, Low severity.)
Both Acunetix and Invicti products now include dedicated security checks to identify any uses of polyfill.io in scanned websites and applications. These are available directly in all Acunetix editions (except Acunetix 360), while Invicti and Acunetix 360 users can enable these custom checks by contacting support.