The TanStack Supply Chain Attack Hiding in Your node_modules
On May 11, 2026, a self-spreading npm worm called Mini Shai-Hulud compromised @tanstack/react-router and 83 other packages in the TanStack namespace — a suite of open-source libraries that powers routing, data fetching, and tables in millions of JavaScript applications.
If your app uses TanStack, and you ran npm install this week, you may have installed a credential stealer.
What Is Mini Shai-Hulud?
Mini Shai-Hulud is a supply-chain worm attributed to a cloud-focused cybercriminal group called TeamPCP. It gets its name from the original Shai-Hulud campaign, a large-scale npm attack from late 2025. This version was smaller but faster, and more sophisticated in how it spread.
The CVE assigned to this attack — CVE-2026-45321 — carries a CVSS score of 9.6 out of 10.
By the time the incident was contained:
- 169 npm packages had been compromised
- 373 malicious package versions were published
- Packages included
@tanstack/react-router,@tanstack/router-core,@tanstack/history,@mistralai/*, and dozens more @tanstack/react-routeralone has 12 million weekly downloads
How the Attack Worked
This is where it gets technical — but it's worth understanding, because it's a lesson in why "the code came from a trusted source" no longer means what it used to.
Step 1: A Fake Pull Request
The attacker created a fork of the TanStack/router repository, renamed it to something innocuous (zblgg/configuration) to avoid showing up in fork lists, and opened a pull request against the main repo.
TanStack's CI was configured with a GitHub Actions pattern called pull_request_target. This pattern runs workflows with write access to the base repository, even when triggered by a fork. It's a known footgun — so well-known it has a name in the security community: the Pwn Request pattern.
Step 2: Cache Poisoning
The attacker's pull request triggered the workflow, which built the project using the attacker-controlled code. That build process poisoned GitHub Actions' shared dependency cache — specifically the pnpm package store — with a tampered version that contained the malware.
Step 3: Stealing the Publishing Key
When TanStack's legitimate release workflow ran next, it pulled from the poisoned cache. The malware in the cached dependencies extracted the GitHub Actions OIDC token from the runner's environment — the short-lived credential that proves a workflow is running in a trusted repository.
GitHub's OIDC federation lets that token be exchanged for a real npm publish token, under TanStack's official publisher identity.
The attacker now had a valid, legitimate credential to publish packages as TanStack.
Step 4: The Worm Spreads
Each malicious package published by the stolen credential contained propagation logic: it would steal credentials from whatever machine installed it, use those to mint more publish tokens, and republish itself into other packages the victim maintained.
This is what makes it a worm rather than a simple trojan. One compromised developer's machine or CI runner could infect every package they maintain.
What the Malware Actually Does
When a compromised package version is installed, two things happen:
1. A hidden script runs. The package includes a heavily obfuscated router_init.js file (~2.3 MB) and an optional dependency pointing to a malicious GitHub commit. npm runs lifecycle scripts for Git dependencies automatically during install — no user interaction required.
2. It harvests every secret it can find:
- GitHub tokens and repository secrets
- npm publish tokens
- AWS credentials — static keys, EC2 metadata, Secrets Manager, Systems Manager
- Kubernetes service account tokens
- HashiCorp Vault tokens
- All environment variables on the system
The stolen credentials are exfiltrated through Session's decentralized peer-to-peer network, disguised as encrypted messaging traffic to make it harder to detect or block.
3. It digs in. The malware writes copies of itself to .claude/ and .vscode/ directories, surviving across reboots and persisting through tool invocations. It also commits back into git repos under stolen maintainer identities.
The Provenance Trap
One of the most important lessons from this attack: the packages were published with valid cryptographic provenance.
Modern npm publishing supports "trusted publishing" — a mechanism where packages include a signed attestation proving exactly which GitHub Actions workflow built them. Security-conscious developers use this to verify that a package came from the expected repository and workflow.
The TanStack packages passed this check. The malicious versions had provenance records showing they were built by TanStack's official workflow.
Because they were. The workflow was simply running attacker-controlled code when it built them.
Provenance tells you where a package was built. It does not prove the build was safe.
What to Do Right Now
If your project depends on any @tanstack/* package, take these steps immediately:
1. Check your lockfile for compromised versions
The malicious versions of @tanstack/react-router were 1.169.5 and 1.169.8. Search your package-lock.json or pnpm-lock.yaml for these version numbers and any TanStack package versions published between May 11 and May 12, 2026.
2. Scan for the malware marker
Look for router_init.js in your node_modules directory:
find node_modules -name "router_init.js"
If it exists, you were affected.
3. Rotate everything
Assume any credentials that existed on machines or CI runners that ran npm install during the affected window are compromised:
- npm tokens
- GitHub personal access tokens and OIDC trusts
- AWS IAM credentials
- Kubernetes service account tokens
- HashiCorp Vault tokens
- Any secrets stored in environment variables
Rotation order matters: revoke the old credentials before creating new ones, or the attacker can use the stolen token to enumerate the replacements.
4. Audit your developer tooling directories
Check .claude/ and .vscode/ directories in your home folder and repositories for any files you didn't put there. Run:
git log --all --author=claude@users.noreply.github.com
to look for unauthorized commits made under stolen maintainer identities.
5. Block the C2 infrastructure
DNS-block *.getsession.org at your network perimeter. This is the exfiltration endpoint the malware uses. If it can't phone home, any remaining infections can't send credentials out.
6. Update to clean versions
TanStack published clean versions as quickly as possible after the compromise was detected. Update to the latest versions and delete any cached versions of affected packages:
npm cache clean --force
rm -rf node_modules && npm install
The Bigger Pattern
This attack is a preview of where supply chain attacks are going. A few things made it particularly effective:
It exploited trust, not weakness. The attack didn't break TanStack's security. It used TanStack's security — their trusted workflows, their verified publisher identity, their signed provenance — against them.
It self-amplified. One compromised workflow became 169 packages. Every developer who installed the malware and maintained their own packages became a new vector. The worm had a multiplier built in.
Provenance failed. The one mechanism most developers rely on to verify supply chain integrity — trusted publishing attestations — couldn't help, because the legitimate workflow was the attack surface.
The security community has been warning about pull_request_target misconfigurations for years. This is what that warning looks like at scale.
This Isn't Hypothetical for Your App
If you use TanStack — and given its download numbers, there's a good chance you do — this attack may have already affected your CI/CD environment. The credentials that deploy your app, write to your database, and access your cloud infrastructure may be in an attacker's hands.
Even if you aren't directly affected, the attack surface this exploited exists everywhere: in every project that uses GitHub Actions with pull_request_target, in every developer whose install commands run lifecycle scripts without inspection, in every CI runner that caches dependencies across workflow runs.
A code review won't just check your code — it looks at your dependency posture, your workflow permissions, and the CI configuration that ships your app. Those are the same vectors Mini Shai-Hulud used.
Talk to us about securing your app's full stack — code, dependencies, and CI/CD.