Polyfill supply chain attack embeds malware in JavaScript CDN assets
26 juin 2024
0 minutes de lectureOn June 25, 2024, the Sansec security research and malware team announced that a popular JavaScript polyfill project had been taken over by a foreign actor identified as a Chinese-originated company, embedding malicious code in JavaScript assets fetched from their CDN source at: cdn.polyfill.io
. Sansec claims more than 100,000 websites were impacted due to this polyfill attack, including publicly traded companies such as Intuit and others.
Frequently Asked Questions
Is Snyk impacted by the Polyfill supply chain security attack?
No, the Snyk platform, including our tooling, is unaffected by the current Polyfill supply chain attack.
Can Snyk detect the Polyfill security issue?
Snyk Code, our real-time and machine learning based SAST engine, can detect a variety of URL usages in functional code. This includes JavaScript, PHP and many other languages.
Here is an example Snyk Code custom rule you can add:
custom_rules:
- id: Polyfill supply chain compromise
description: >-
The polyfill.js is a popular open source library to support older
browsers. This domain was caught injecting malware on mobile devices via
any site that embeds cdn.polyfill.io.
severity: high
cwe:
- CWE-506
fix_analysis: Use alternatives provided at HTTPS cdnjs.cloudflare.com SLASH polyfill
rule_code: >-
StringLiteral<~".*https://cdn.polyfill.io.*">
languages:
- html
- javascript
- php
- java
Such a rule will successfully detect the usage of any cdn.polyfill.io URL within JavaScript or PHP code. For example, in this code snippet, the manual script inclusion will be detected:
1<!DOCTYPE html>
2<html lang="en">
3<head>
4 <meta charset="UTF-8">
5 <meta name="viewport" content="width=device-width, initial-scale=1.0">
6 <title>Load Polyfill</title>
7</head>
8<body>
9 <script>
10 // Load the polyfill for Array.prototype.includes from cdn.polyfill.io
11 (function() {
12 var script = document.createElement('script');
13 script.src = "https://cdn.polyfill.io/v3/polyfill.min.js?features=Array.prototype.includes";
14 script.onload = function() {
15 // Polyfill is loaded, you can use Array.prototype.includes safely now
16 console.log([1, 2, 3].includes(2)); // Should log 'true'
17 };
18 document.head.appendChild(script);
19 })();
20 </script>
21</body>
22</html>
23
Note: the custom rule will only match JavaScript or PHP code and not plain <script src=“…”></script>
tags in HTML.
Should I only add a denylist rule for cdn.polyfill.io website?
Many reports have been recorded that newer domains have been added by the malicious actor, some of which are: polyfill[.]site , polyfill[.]com , bootcdn[.]net , bootcss[.]com staticfile[.]net staticfile[.]org , unionadjs[.]com , xhsbpza[.]com , union.macoms[.]la , newcrbpc[.]com. It’s highly advised that you monitor these reports closely and update your Snyk Code custom rule accordingly.
What happened with the malicious polyfill library?
In February 2024, a Chinese company announced that it would acquire the polyfill.io website from the Node.js polyfill-library creator Jake Champion and the website owner. The Chinese company, Funnull, which provided CDN and hosting services, stepped in and has since been the owner of the domain and GitHub organization and repository.
Soon after this acquisition announcement, the polyfill.io domain featured a new CNAME to polyfill.io.bsclink.cn
.
Signals of this soon-to-unfold catastrophe were made in developer circles, such as the following GitHub comment by Renaud Chaput:
More signals of foul play were also made throughout April and June by community users who raised the alarm concerning the transfer of ownership to a third-party company, strengthening suspicions even more when their comments were deleted on a GitHub issue:
Following the above, Andrew Betts, a colleague of Jake Champion, at Fastly was the original author of the polyfill web service. This project allowed the automatic injection of JavaScript polyfill libraries into websites based on their user agent or other properties. Andrews's statements trace back to February when they warned of having no part in the official cdn.polyfill.io
website.
There is no specific polyfill library on npm that we know is part of this specific malicious actor campaign to inject malicious code. That said, libraries across different software ecosystems, such as Content Management systems like the Magento project and others, might include code that introduces static script imports of JavaScript code sourced from cdn.polyfill.io
. In particular, we have detected CVE-2024-38526, a security report for the pdoc
library on PyPI registry that provides API Documentation for Python Projects. In cases where documentation is generated with the command pdoc --math
would contain links to JavaScript files from polyfill.io
. This behavior of the pdoc
library has been fixed in pdoc version 14.5.1, and we urge users to upgrade as soon as possible.
What is the current state of affairs with the polyfill.io website?
The polyfill.io website is now effectively offline. In further action to protect end-users, ad blocker browser extensions such as uBlock have now kept up with reports about the polyfill.io website and are actively preventing access to it to keep users safe.
On June 21st, Google was reported to roll out a “compromised website” error message on the Google Ads application website, which escalated due to reports of googie-anaiytics[.]com
domain website spoofing attempts.
What is the impact of polyfill.io malware?
In 2017, Andrew Betts, the original author of the polyfill.io website that was hosted on Fastly, reported a whopping 91 million browsers per day issuing requests to import the library and up to 700 million requests per month to upgrade older browsers with modern web standards.
Reports on social media and other sources have noted that the Hulu company website is bundling the JavaScript library from the cdn.polyfill.io website, which was found to be malicious (reported by Theo).
In another report by Germán Fernández, the Atlassian community website has also been identified as importing the JavaScript polyfill library from the malicious polyfill.io domain.
Government websites were also identified by Silent Push Labs to include the malicious polyfill.io source and were reported to CISA.
What is a JavaScript polyfill?
A JavaScript Polyfill is often a purposely built piece of code that provides modern functionality on older browsers that do not natively support it. Historically, polyfills were crucial for web developers aiming to create applications that work seamlessly across different browser versions. They act as a bridge, enabling older browsers to run newer JavaScript features, ensuring a consistent user experience regardless of the browser's age or capabilities.
In the early days of web development, browsers evolved at different paces, leading to a fragmented environment where the same code might not run uniformly across all platforms. Generally speaking, support for browser APIs would not be equally supported. With no control over browser versions available to end-users, developers couldn’t guarantee the same API available when JavaScript code executed in browsers. As such, polyfills emerged as a solution to this problem by introducing polyfill libraries, allowing developers to write modern JavaScript code without worrying about compatibility issues. For example, methods like Array.prototype.includes
and Promise
were not supported in older browsers like Internet Explorer. Still, developers could make these features available with a polyfill library loaded in the browser.
The role of a JavaScript CDN in polyfill libraries
A Content Delivery Network (CDN) is a system of globally deployed and distributed servers that deliver web content to users based on their geographic location. In the context of JavaScript polyfill libraries, CDNs play a vital role by hosting and serving these libraries efficiently across the globe. By leveraging CDNs, developers ensure that their polyfills are delivered quickly and reliably to users, minimizing latency and improving load times. Using a CDN was also helpful to developers to avoid the need to bundle JavaScript libraries.
A general use case for a CDN that you are likely to encounter is the use of cloud-based metrics and application performance, such as Google Analytics, which officially proposes that you add the following code to your website:
1<script async custom-element="amp-analytics" src="https://cdn.ampproject.org/v0/amp-analytics-0.1.js"></script>
2<amp-analytics type="gtag" data-credentials="include">
3<script type="application/json">
4{
5 "vars" : {
6 "gtag_id": "<GA_MEASUREMENT_ID>",
7 "config" : {
8 "<GA_MEASUREMENT_ID>": { "groups": "default" }
9 }
10 }
11}
12</script>
13</amp-analytics>
In the case of the malicious polyfill takeover, cdn.polyfill.io
was a widely used CDN that dynamically served polyfills based on the HTTP headers of incoming requests. This meant that the appropriate polyfill was delivered based on the user's browser and version, ensuring optimal compatibility.
Security risks of polyfills hosted on a CDN
Using polyfills hosted on a CDN introduces significant security risks, primarily due to the potential for arbitrary JavaScript code execution within the application context. This risk is often reported as a Cross-site Scripting (XSS) vulnerability for a given web application.
When a polyfill library is fetched from a CDN, the application relies on the integrity and security of the external server. As in the CDN source in itself. If the CDN or the hosted library is compromised, as seen in the recent attack on cdn.polyfill.io
, the newly compromised code can be injected and executed within the user's browser. Such malicious code can perform various nefarious activities, such as redirecting users to phishing sites, stealing sensitive information, or even further propagating malware. When it comes to browser security, this sort of XSS vulnerability is the most severe consequence.
How could Snyk detect vulnerable JavaScript libraries on a CDN?
Beyond detecting insecure code and vulnerable third-party libraries in your project manifest and project dependencies, the Snyk VS Code extension also supports detecting vulnerable libraries that were imported using static script import statements.
For example, if the lodash
library imported from a CDN were to use a vulnerable version range or was known to include malicious code, Snyk will append in-line annotations to drive the developer’s attention to the security risk.
Protecting against CDN supply chain attacks
The recent attack on the JavaScript polyfill project highlights the critical importance of supporting resources across the web ecosystem, and CDNs are a significant part of that. Supply chain security concerns often revolve around open source package registries such as PyPI and npm but the JavaScript polyfill attack reminded us that CDNs are also an incredible building block of the web.
Following are some best practices you should consider to help protect from such attacks:
Use trusted CDNs: Only use CDNs from reputable providers. For example, Cloudflare is well-known for its robust security measures and reliability.
Replace polyfill clone: Cloudflare introduced a polyfill clone at https://cdnjs.cloudflare.com/polyfill, which they recommend you use as a drop-in replacement.
Monitor dependencies: Regularly audit and monitor all third-party scripts and dependencies.
Subresource integrity: Tools like Subresource Integrity (SRI) can help ensure that the content delivered by a CDN has not been tampered with and can be pinned to an expected version/hash that has been audited and known to be clear of malicious or otherwise undesired behavior.
Content Security Policy (CSP): Implement a strong CSP to restrict the sources from which scripts can be loaded. This can prevent malicious scripts from being executed. Since polyfills are often included in the critical path of application loading, they run with the same permissions as any other JavaScript on the page, making them a prime target for attackers aiming to exploit this trust. This risk underscores the importance of using secure and reputable CDNs, implementing robust security measures like Content Security Policy (CSP), and regularly auditing third-party dependencies to safeguard against such vulnerabilities.
Regular updates: Keep all libraries and dependencies up-to-date. Many attacks exploit known vulnerabilities that have been patched in later versions.
Alternative solutions: Evaluate whether polyfills are still necessary for your project. As browsers modernize, many features provided by polyfills are now natively supported. Highly consider vendoring your dependencies with your own project assets instead of reliance on third-party providers such as CDNs.