On the evening of May 11, 2026, between 19:20 and 19:26 UTC, an attacker published 84 malicious versions across 42 @tanstack/* npm packages β including @tanstack/react-router, a routing library with roughly 12 million weekly downloads. Within the same 48-hour window the same actor, tracked as TeamPCP, also poisoned @mistralai/mistralai, the mistralai==2.4.6 PyPI release, @uipath/* automation SDKs, OpenSearch JavaScript clients, and guardrails-ai==0.10.1 on PyPI. In total, researchers counted 373 malicious package-versions across 169 package names in this wave alone.
Two things make this incident different from the three earlier Shai-Hulud and Mini Shai-Hulud waves we’ve covered. First, the attacker never stole a credential. Second, the malicious packages carried valid SLSA Build Level 3 provenance attestations β the same cryptographic guarantee that npm and Sigstore have been telling teams to rely on. The compromise is being tracked as CVE-2026-45321 (CVSS 9.6).
How the attack worked
TanStack’s postmortem and StepSecurity’s reconstruction line up on the mechanics. The attacker chained three primitives:
Pwn Request on
pull_request_target. They forkedTanStack/routertozblgg/configuration(a name designed to evade fork-list searches), then opened a PR that triggered a workflow running underpull_request_target. That trigger checks out the PR’s code while running with secrets and write tokens from the base repo β the textbook “Pwn Request” pattern Adnan Khan has been warning about since 2023.GitHub Actions cache poisoning across the forkβbase trust boundary. The fork’s workflow run wrote to the same
actions/cachenamespace the base repo’s release pipeline reads from, planting a maliciouspnpmstore. When the next legitimate release workflow ran onmain, it restored the poisoned cache and executed attacker-controlled binaries duringpnpm install.Runtime OIDC token extraction from runner memory. The poisoned binaries opened
/proc/<pid>/mapsand/proc/<pid>/memon theRunner.Workerprocess, scanned for the OIDC JSON Web Token the runner uses to authenticate to npm’s trusted publishing endpoint, and used that token to publish 84 malicious versions directly β bypassing the workflow’s own publish step entirely.
Because the publish happened via the legitimate OIDC identity, npm’s trusted-publisher infrastructure dutifully signed the artifacts and issued SLSA L3 provenance attestations. This is the first documented npm worm that produces validly-attested malicious packages. Provenance tells you a package was built by TanStack/router’s pipeline. It does not tell you that pipeline wasn’t carrying a passenger.
What the payload does
The implant is a credential stealer with worm behavior, consistent with prior Mini Shai-Hulud waves but with a few additions. The mistralai PyPI variant pulls a second-stage stealer from 83.142.209[.]194, includes locale-aware logic that skips Russian-language environments, and ships a destructive branch that fires when it detects Hebrew or Farsi locales β wiping the developer’s home directory.
On npm, the worm hunts for the same secrets that made the original Shai-Hulud famous: ~/.npmrc tokens, GITHUB_TOKEN, AWS/GCP/Azure credential files, kubeconfig, SSH keys, and any OIDC_* environment variable in the current process tree. Anything it finds gets exfiltrated to a hardcoded public GitHub repo named in the same Sh1-Hulud-* pattern as previous waves, then used to publish further malicious versions of any package the stolen tokens can reach.
Who’s affected
If your build ran any of the following between 19:20 UTC on May 11 and roughly 22:00 UTC on May 12 (when registries finished unpublishing), you should treat it as a credential exposure event:
@tanstack/*β 42 packages, 84 malicious versions. The most-installed is@tanstack/react-router; see Snyk’s IOC list for the full set.@mistralai/mistralai(npm) andmistralai==2.4.6(PyPI).@uipath/*β apollo-core, CLI, agent SDKs.@opensearch-project/*JS clients.guardrails-ai==0.10.1(PyPI).- Two compromised
@squawk/*packages.
Last clean versions before the attack: mistralai==2.4.5 (PyPI, May 7), @mistralai/[email protected] (npm). Snyk, Aikido, and Socket each publish full version manifests; pin against those, not against the npm registry’s “latest” tag, which was still pointing at malicious versions for several hours.
What to do now
This is not a “rebuild your lockfile and move on” incident. Anyone whose CI pulled a poisoned version had OIDC tokens, npm publish tokens, and any cloud credentials in the runner’s environment exposed.
Rotate, in this order: any npm trusted-publisher OIDC subject claims tied to affected packages; long-lived NPM_TOKEN secrets in repos that depend on the affected packages; GITHUB_TOKEN PATs scoped to those repos; cloud credentials and kubeconfigs present on any runner that executed an install. Then audit your own published packages for versions you don’t recognize β the worm’s whole point is to lateral-move.
On the workflow side, the structural lessons are the ones the GitHub Actions hardening guides have been making for two years: never combine pull_request_target with actions/checkout of ${{ github.event.pull_request.head.sha }}; never share actions/cache namespaces between fork and base workflows (set distinct key prefixes that include github.event_name); and consider GitHub’s restricted-cache feature, which gates cache restores on the workflow that wrote them. StepSecurity’s harden-runner action will catch the /proc/*/mem read at runtime β that’s what caught this attack 20 minutes after publish.
The harder lesson is about provenance. SLSA Build L3 attestations are still worth having; they raise the cost of unsigned typo-squat attacks dramatically. But they prove a build happened in the claimed pipeline, not that the pipeline was uncorrupted at the moment of build. Treat provenance as a necessary condition, not a sufficient one, and keep doing behavioral analysis of installed packages β at least for anything reaching CI/CD or production.
References
- TanStack postmortem: https://tanstack.com/blog/npm-supply-chain-compromise-postmortem
- StepSecurity analysis: https://www.stepsecurity.io/blog/mini-shai-hulud-is-back-a-self-spreading-supply-chain-attack-hits-the-npm-ecosystem
- Snyk IOCs and version list: https://snyk.io/blog/tanstack-npm-packages-compromised/
- Wiz writeup: https://www.wiz.io/blog/mini-shai-hulud-strikes-again-tanstack-more-npm-packages-compromised
- The Hacker News overview: https://thehackernews.com/2026/05/mini-shai-hulud-worm-compromises.html
- BleepingComputer on the SLSA provenance angle: https://www.bleepingcomputer.com/news/security/shai-hulud-attack-ships-signed-malicious-tanstack-mistral-npm-packages/
- The Register’s mechanical breakdown: https://www.theregister.com/cyber-crime/2026/05/12/cache-poisoning-caper-turns-tanstack-npm-packages-toxic/5238650