
On May 11, 2026, a worm published 84 malicious npm versions across 42 @tanstack/* packages โ and they shipped from a trusted publishing pipeline.
If your security model assumes that “signed by the right pipeline” means “safe to install,” May 11 was the warning.
npm provenance is a build-pipeline attestation: it cryptographically proves which workflow produced a package, but not whether that workflow ran honest code.
What happened
On May 11, 2026, between 19:20 and 19:26 UTC, an attacker pushed 84 versions across 42 @tanstack/* packages. An external researcher caught it within twenty minutes.
By then, every install in that window had pulled the payload. The Mini Shai-Hulud worm does not stop at the first victim.
It harvests credentials, enumerates every npm package the compromised maintainer owns, and publishes infected versions of each. By the time the dust settled, well over a hundred package names were touched โ TanStack, UiPath, DraftLab, OpenSearch, Mistral AI, and others.
The campaign crossed registries. Wiz
documented PyPI variants in guardrails-ai@0.10.1 and mistralai@2.4.6 calling home to git-tanstack[.]com. Block that domain at egress.
The attack chain
The chain had three links, each individually known.
Three known patterns, chained. Each link survives a defender who only knows the other two.
First, a pull_request_target workflow ran untrusted fork code with read-write context โ the “Pwn Request” pattern documented since 2021.
Second, the attacker poisoned the GitHub Actions cache with a 1.1 GB pnpm store, keyed to match what the production release workflow would later restore.
Third, when release ran, attacker binaries scraped the OIDC token directly from the runner’s /proc/<pid>/mem โ the token that signs npm provenance attestations. No npm token was stolen. The attacker did not need one.
What npm provenance actually attests (and what it doesn’t)
npm trusted publishing was supposed to fix the credential-theft class of attack. You don’t ship a long-lived NPM_TOKEN; the runner mints a short-lived token via OIDC, and the artifact gets a provenance attestation tying it to the workflow that produced it.
The TanStack postmortem puts the gap cleanly: “OIDC trusted-publisher binding has no per-publish review. Once configured, any code path in the workflow can mint a publish-capable token.”
Translation: provenance answers “did this come from the right pipeline.” It does not answer “was the pipeline honest.”
StepSecurity describes this as the first documented npm worm to publish validly-attested malicious packages.
A trust signal that cannot distinguish a legitimate build step from a malicious one is not a trust signal. It is notarization.
Provenance is a non-human identity problem
Last week in AppSec Santa #8 I argued that non-human identities โ CI tokens, OAuth grants, agent sessions โ are the new primary AppSec attack surface. The provenance attestation is the same story, one layer deeper.
Provenance is one more badge on the non-human identity wall. The seal does not certify the contents.
The OIDC token that signs your provenance is itself a non-human identity. Its trust derives from a workflow definition, not from a person reviewing the artifact.
When the workflow can be coerced into running attacker code, the attestation becomes a signed declaration of compromise. Treat provenance the way you would treat any other signature from a non-human identity: it tells you who claimed what. It does not tell you whether the claim is true.
Six things to do this week, in order
- Hunt for persistence before touching any tokens. Search for the
gh-token-monitordaemon at~/Library/LaunchAgents/com.user.gh-token-monitor.plist(macOS) or~/.config/systemd/user/gh-token-monitor.service(Linux), and forsetup.mjsorrouter_runtime.jsin~/.claude/and~/.vscode/. Token revocation triggersrm -rf ~/on infected hosts. Sequence matters. - Inventory Claude Code
SessionStarthooks, VS Code folder-open tasks, and OS-level launch agents on every developer machine. The worm planted persistence in all three, and those files survivenpm uninstall. - Then rotate credentials. Scan the full list of 100+ credential paths the worm targets, not just
~/.aws/credentialsand~/.npmrc. The complete list is in the StepSecurity writeup. - Audit every
pull_request_targetworkflow in your org. Default topull_requestwith explicit fork checkouts when you genuinely need fork context. - Scope OIDC trusted publishers to one workflow file and one branch ruleset. The blast radius of a compromised workflow is whatever the publisher trusts.
- Treat the GitHub Actions cache as untrusted input. Pin restore keys to commit SHA, not branch name.
The lesson: provenance is notarization, not honesty
Provenance isn’t honesty. It’s notarization of who claimed what. The attacker’s claim was perfectly notarized on May 11. That is the lesson.
What else shipped this week
A few releases worth flagging, in case the supply-chain thread above runs through them.
- GitGuardian
v1.50.4 โ
ggshield plugin install --allow-unsignednow verifies plugin signatures against an embedded Sigstore trust root instead of refreshing it over the network. The exact failure mode this week’s piece is pointing at: an attestation chain you cannot verify offline is an attestation chain with a network dependency on its trust roots. - Checkov 3.2.527 โ 3.2.528 โ Bridgecrew shipped a multiline-regex secrets detection fix, reverted it three days later in 3.2.527, then re-applied it the next day in 3.2.528. Same code shipped twice with a public reversion in between. Pin minor versions in CI.
- OSV-Scanner
v2.3.8 โ Switches file path handling to
os.OpenRoot, a structural fix to scope file operations to a single directory tree. The right pattern: address the class, not the instance. - Semgrep v1.162.0 โ JSON rule parsing is now ~5ร faster (382 MB rule pack: 134 s โ 28 s) via a hand-written RFC 8259 parser. If your CI was waiting on rule load, that wait just shrank.
- Cisco DefenseClaw 0.4.0 โ 0.5.0 โ Two releases this week on Cisco’s open-source AI-traffic security tool. Connector architecture v3 plus a non-interactive command generator. The first concrete shape of Cisco’s AI-defense playbook after the Astrix announcement I covered in last week’s #8 issue.
61 releases tracked across 7 categories. Reply if you want the full per-category breakdown back next week โ I dropped it for W19 to make space for the thesis pieces, but the data is still being collected.
Reply if I missed something. I’ll update the piece.