Yesterday at 19:20 UTC, an attacker published 84 malicious npm packages across the entire @tanstack ecosystem. By 19:26 — six minutes later — the attack was done. By the time most developers woke up, their CI pipelines had already pulled the compromised versions.
This is Mini Shai-Hulud Wave 3. It's the most technically sophisticated npm supply chain attack on record. And it matters to anyone who vibe codes.
What happened
The attacker, attributed to threat group TeamPCP, didn't steal anyone's credentials. Instead, they used a chained GitHub Actions attack:
- Created a fork of
TanStack/routernamedzblgg/configuration— deliberately obscured to avoid appearing in fork-list searches - Opened a pull request that triggered a
pull_request_targetworkflow (a known dangerous pattern that grants write permissions to fork code) - The malicious fork code poisoned the GitHub Actions runner cache with a malicious
pnpmstore - When a legitimate TanStack maintainer PR was merged and the release workflow ran, it restored the poisoned cache
- The attacker's code then extracted OIDC tokens directly from the GitHub Actions runner's process memory (
/proc/<pid>/mem) - Used those tokens to publish 84 malicious package versions — with the project's own trusted OIDC identity
The result: 84 malicious versions with valid SLSA provenance. Automated security scanners that only check signatures saw legitimately signed packages. This is the first documented case of this technique succeeding at scale.
What the malware does
Every compromised package contained router_init.js — a credential harvester that:
- Exfiltrates AWS, GCP, Azure, GitHub, npm, and SSH credentials
- Targets crypto wallet keys
- Drops persistence files into
.claude/and.vscode/directories - Sends everything to
api.masscan.cloud,git-tanstack.com, and*.getsession.org
The payload runs on npm install. No user interaction. No suspicious prompts.
Are you affected?
You are potentially affected if you ran npm install between 19:20 and 19:26 UTC on May 11, 2026, and your project directly or transitively depends on any of these packages:
@tanstack (router/start packages):
@tanstack/react-router— versions1.169.5,1.169.8@tanstack/vue-router— versions1.169.5,1.169.8@tanstack/solid-router— versions1.169.5,1.169.8@tanstack/router-core— versions1.169.5,1.169.8@tanstack/react-start— versions1.167.68,1.167.71@tanstack/router-plugin— versions1.167.38,1.167.41- 36 additional
@tanstack/router-*and@tanstack/start-*packages
@mistralai:
@mistralai/mistralai—2.2.2,2.2.3,2.2.4@mistralai/mistralai-azure—1.7.1,1.7.2,1.7.3@mistralai/mistralai-gcp—1.7.1,1.7.2,1.7.3
@opensearch-project:
@opensearch-project/opensearch—3.5.3,3.6.2,3.7.0,3.8.0
Check your lockfile right now:
# Check for malicious @tanstack versions
grep -E "@tanstack/(react|vue|solid)-router|@tanstack/router-core" package-lock.json | grep -E "1\.169\.[58]"
grep -E "@tanstack/react-start" package-lock.json | grep -E "1\.167\.(68|71)"
# Check Mistral
grep "@mistralai/mistralai" package-lock.json | grep -E "2\.2\.[234]"
# Check OpenSearch
grep "@opensearch-project/opensearch" package-lock.json | grep -E "3\.(5\.3|6\.2|7\.0|8\.0)"
Or paste your lockfile into VibeScan — it now detects all 42 affected packages and their malicious version ranges automatically.
If you are affected: what to do
Do not just npm install a new version and move on. If the malicious package ran on your machine or in CI, treat the entire host as compromised.
Immediate steps:
-
Rotate everything the install host could reach:
- AWS/GCP/Azure IAM credentials and access keys
- GitHub personal access tokens and deploy keys
- npm publish tokens
- SSH private keys
- Vault/secrets manager credentials
- Kubernetes service account tokens
- Any crypto wallet keys in the environment
-
Check for persistence drops:
ls -la .claude/ ls -la .vscode/ # Look for unexpected files added after 2026-05-11 -
Audit CI logs for any unauthorized publishes or API calls on May 11
-
Upgrade the package:
npm install @tanstack/react-router@latest # Replace with whatever TanStack packages you use -
Re-run
npm installon a clean machine after credential rotation
Why this keeps happening to vibe-coded apps
The developers I talk to who build with Lovable, Bolt, and Cursor are adding packages fast. An AI suggests @tanstack/react-router for routing, you accept, it gets added to package.json. You're not thinking about whether that package's release pipeline has a pull_request_target misconfiguration.
That's not a criticism — it's a structural problem. Vibe coding optimizes for speed. Security requires knowing which packages have trustworthy supply chains, which versions are clean, and when a new attack breaks. No one can track that manually.
The @tanstack team has since fixed their pipeline. The malicious versions have been unpublished. But they were live for six minutes, and automated package managers pulled them.
What this means practically:
- Lock your dependencies (
package-lock.jsonoryarn.lockcommitted) - Don't run
npm installin unreviewed CI contexts without pinned versions - Check your lockfile against IOC databases when supply chain attacks break — not just CVE databases, which lag by days or weeks
VibeScan's lockfile scanner now has a hardcoded IOC table for this attack that runs before OSV lookup. It takes 30 seconds to check a lockfile.
About VibeScan
VibeScan scans the deployed surface of AI-built apps — exposed credentials, missing RLS, BOLA/IDOR, CORS, rate limiting, and now supply chain IOCs in lockfile scans. No GitHub access required. Try it free.