DEV Community

Pico
Pico

Posted on • Originally published at getcommit.dev

I Scored Every Compromised npm Package From May 2026. Four Out of Five Attacks Were Predictable.

Five major npm supply chain attacks hit in three weeks. Over 1,100 malicious package versions published. Credential harvesters, self-propagating worms, and a CI/CD bypass that beat provenance attestation.

I scored every compromised package through getcommit.dev — behavioral supply chain scoring that measures structural risk signals like publisher concentration, release patterns, and provenance.

Six out of seven packages scored below 75 before they were attacked. The only one that scored healthy was attacked through a completely different vector.

The timeline

Date Target Malicious versions Attack vector
Apr 30 intercom-client 1 Compromised GitHub account → CI/CD publish
May 11 TanStack (42 packages) 84 GitHub Actions cache poisoning + OIDC extraction
May 14 node-ipc 3 Stolen npm credentials
May 19 @antv ecosystem (323 packages) 639 Self-propagating worm (Shai-Hulud)
May 22 700+ GitHub repos ~700 Malicious postinstall hooks

Over 1,100 compromised versions in 23 days. npm has never seen a month like this.

The scores

Every package scored through Commit's behavioral audit, using data available before each attack:

Package Score Publishers Downloads/wk Provenance Risk flag
size-sensor 66 1 1.1M No HIGH
timeago.js 67 2 260K No WARN
node-ipc 69 1 900K No WARN
intercom-client 69 1 381K Yes
echarts-for-react 71 1 1M No
jest-canvas-mock 72 2 2.6M No WARN
@tanstack/react-router 91 5 16.8M Yes

Six packages scored between 66 and 72. One scored 91.

The six low-scoring packages were all compromised through credential theft — stolen npm tokens or compromised GitHub accounts. The one high-scoring package was attacked through a three-step CI/CD pipeline exploit that bypassed provenance attestation entirely.

What the low scores share

The six credential-theft targets have a consistent structural profile:

  • 1-2 npm publishers. Every one. The attack surface is a single credential.
  • No or stale releases. node-ipc hadn't published in 21 months. jest-canvas-mock: nearly 3 years. Dormant accounts are easier to steal.
  • No provenance. Five of six had no OIDC attestation linking source to release. intercom-client had provenance, but the attacker compromised the GitHub account that the CI workflow ran under — provenance proved the malicious build came from CI, which was true.

This is the same pattern behind the LiteLLM attack (March 2026) and the axios compromise (March 30, 2026). Single publisher. Dormant or stale. No cryptographic chain of custody.

Why TanStack is the outlier

TanStack scored 91. Five publishers. Active development — last publish 3 days before the attack. Provenance enabled.

The attackers didn't steal anyone's credentials. They chained three GitHub Actions vulnerabilities:

  1. pull_request_target workflow (lets fork code run with base repo permissions)
  2. Cache poisoning across the fork → base trust boundary
  3. Runtime memory extraction of the OIDC token from the Actions runner

The malware published 84 versions across 42 packages in six minutes. It passed SLSA provenance checks. Every tool looking at cryptographic proof of origin said "legitimate."

Socket's AI scanner flagged the packages within six minutes of publication. But behavioral scoring couldn't have predicted this — the structural signals were all healthy.

The pattern is clear

Four out of five attack events used credential theft against structurally weak packages. One used a sophisticated CI/CD exploit against a structurally strong one.

Behavioral signals catch the common attack. Provenance attestation is supposed to catch the sophisticated one — but TanStack proved it can be bypassed when the CI environment itself is compromised.

No single signal catches both. But the common attack — the one that keeps repeating, month after month — has a structural signature that's visible before it happens.

The uncomfortable count

There are 26 npm packages with over 10 million weekly downloads and a single npm publisher. Every one shares the structural profile of the packages attacked this month:

minimatch    — 593M/wk, 1 publisher  CRITICAL
chalk        — 410M/wk, 1 publisher  CRITICAL
glob         — 346M/wk, 1 publisher  CRITICAL
cross-spawn  — 206M/wk, 1 publisher  CRITICAL
zod          — 181M/wk, 1 publisher  CRITICAL
Enter fullscreen mode Exit fullscreen mode

These aren't in your package.json. They're in your lock file.

Check your own tree

npx proof-of-commitment --file package-lock.json
Enter fullscreen mode Exit fullscreen mode

Scans your full dependency tree and flags the structural risks that npm audit doesn't look at.

getcommit.dev/audit — paste packages, see scores. No install.


Data sources: Socket.dev incident reports, npm registry, getcommit.dev behavioral scoring. All scores use data available prior to each incident.

Top comments (0)