OIDC Provenance Didn’t Save TanStack or Red Hat. npm Staged Publishing Is the Missing Gate.
Two attacks, both with valid SLSA attestations. The gap is between CI and latest.
Two major supply chain attacks in six weeks. Both targeted packages with OIDC provenance enabled. Both succeeded.
TanStack (May 11, 2026): 42 packages, 84 malicious versions in 6 minutes. Attacker exploited GitHub Actions pull_request_target + cache poisoning + OIDC token extraction from runner memory. 16.8M weekly downloads on @tanstack/react-router alone. All published versions had valid SLSA attestations.
Red Hat @redhat-cloud-services (June 1, 2026): 32 packages republished with credential-stealing malware. Attacker compromised a GitHub account, pushed orphan commits, triggered the existing CI pipeline. The pipeline built the malware, published it to npm using its own OIDC tokens, and generated valid SLSA provenance. Provenance proved “this was built by Red Hat’s CI”—which was true. The CI just happened to be building malware.
Provenance answers the wrong question
OIDC provenance answers: “Was this built by the expected pipeline?”
When the pipeline is compromised, the answer is yes. The attestation is valid. The malware is signed.
This is the gap. Provenance proves where a build came from. It doesn’t prove the CI pipeline wasn’t tampered with.
npm Staged Publishing closes it
npm Staged Publishing (GA May 2026) adds a human approval gate between CI publishing a version and that version becoming the default npm install target.
Without Staged Publishing:
CI runs → npm publish → version is live immediately With Staged Publishing:
CI runs → npm stage → version sits in holding → human 2FA approval → version goes live
In both the TanStack and Red Hat scenarios, malicious versions would have sat in a staging area. No silent pushes to latest. A human would need to review and approve each one.
PostCSS maintainer Andrey Sitnik made this point directly in postcss/postcss#2096: “CI-as-publisher increased the attack risks compared to 2FA manual publishing.” He was right—and the incidents proved it.
Detection
npm doesn’t surface whether a package uses Staged Publishing. Registry metadata doesn’t include it unless a version is actively staged. CI workflow files might reference npm stage commands, but nobody checks those at dependency-install time.
We added Staged Publishing detection to Commit this week. Two-tier detection:
1. dist-tags check—if a stage dist-tag exists in the registry, the package is actively using staged publishing. Zero extra API calls—it’s already in the registry response.
2. GitHub Actions workflow scan—looks for npm stage, @npm/staged-publish, or staged-publish patterns in the package’s CI configuration.
The result shows up in scoreBreakdown.stagedPublishing on the API response and in the CLI output.
First detected adopters: nanoid, nanospy, preact
On June 19, 2026, Andrey Sitnik moved nanoid (208M weekly downloads) and nanospy to Staged Publishing. He confirmed it on postcss/postcss#2096: “I already moved nanoid and nanospy to the new process, we can test them.”
Commit picked up both within the registry cache window. Live JSON: nanoid and nanospy — both return hasStagedPublishing: true with stagedPublishing: 2/2 in the score breakdown.
The trigger was the npm stage publish step in nanoid’s release.yml. PostCSS itself still reads false — Sitnik said that one’s coming in a week or two. When he flips it, the score updates automatically.
Independently detected: preact. Sweeping the top of the npm tree the same afternoon turned up preact (23M weekly downloads) — quietly using staged publishing with no public announcement. Live JSON: preact returns hasStagedPublishing: true. The trigger sits on line 118 of preact’s release.yml: npm stage publish preact.tgz --provenance --access public. Provenance and staged publishing, both shipped, no press release.
That’s the test: can scoring track the new gate as maintainers actually adopt it — including the ones who didn’t announce? On both signal types, yes.
Check your dependencies
npx proof-of-commitment This scans your lockfile and flags packages where a single npm publisher controls >10M weekly downloads—the exact attack surface that’s been exploited three times since March. The output now includes whether each package uses OIDC provenance, Staged Publishing, or neither.
If you see CRITICAL with no provenance and no staged publishing—that package is one stolen credential away from the next incident. And the credential doesn’t have to be an npm token anymore. It can be a GitHub account, a CI cache, or an OIDC token extracted from process memory.
The supply chain moved past “just use provenance” in May 2026. The question now is which packages have caught up.
Free API key watches 3 packages with a weekly digest. Developer ($15/mo) watches 15 with daily scans and instant alerts — the moment a score drops, before the version reaches your tree.