
IOC checker for the TanStack/Mini Shai-Hulud npm supply chain attack (CVE-2026-45321)
curl -fsSL https://raw.githubusercontent.com/nkopylov/tanscript-exploit-check/main/check-tanstack-exploit.sh | bash
Or clone and run locally:
git clone https://github.com/nkopylov/tanscript-exploit-check.git
cd tanscript-exploit-check
./check-tanstack-exploit.sh [project_dir ...]
This checker covers two waves of the Mini Shai-Hulud supply chain attack campaign by TeamPCP:
On May 11, 2026 (19:20-19:26 UTC), an attacker published 84 malicious versions across 42 @tanstack/* npm packages in a 6-minute window. The attack also hit packages from Mistral AI, UiPath, OpenSearch, and others — over 170 packages total across npm and PyPI.
No maintainer credentials were stolen. The attacker exploited the CI/CD trust chain itself via a 3-stage attack:
pull_request_target exploit — A throwaway GitHub fork opened a PR that ran attacker code in the base repo's security contextOn May 19, 2026 (01:39-02:06 UTC), the compromised atool npm account ([email protected]) published 637 malicious versions across 314 packages in two automated waves. High-impact targets include:
size-sensor (4.2M downloads/month)echarts-for-react (3.8M downloads/month)@antv/scale (2.2M downloads/month)timeago.js (1.15M downloads/month)@antv/* and other packagesThis wave used a Bun-based payload (498KB index.js) triggered via "preinstall": "bun run index.js", with a second-stage payload hidden in imposter commits pushed to the antvis/G2 GitHub repo via the fork object sharing exploit.
Both waves use the same "Mini Shai-Hulud" toolkit family:
gh-token-monitor (Wave 1) and kitty-monitor (Wave 2) daemons via LaunchAgent/systemd; hooks in .claude/settings.json and .vscode/tasks.jsontoJSON(secrets), npm OIDC token exchangerm -rf ~/ if GitHub token revoked while daemon activefiredalazer keyword, RSA-PSS signed commands| # | Check | Description |
|---|---|---|
| 1 | Dead-man's switch | Persistence daemons: gh-token-monitor (Wave 1), kitty-monitor (Wave 2) |
| 2 | Malicious processes | Known attacker process names (both waves) |
| 3 | Payload files | Known malicious files by name and SHA-256 hash (4 hashes) |
| 4 | Claude Code hooks | Injected hooks in .claude/settings.json + generic SessionStart heuristic |
| 5 | VS Code tasks | Injected tasks in .vscode/tasks.json + generic runOn: folderOpen heuristic |
| 6 | GitHub Actions | toJSON(secrets) in any workflow + pull_request_target warning |
| 7 | npm lockfiles | Compromised package versions in lockfiles |
| 8 | optionalDependencies | Malicious @tanstack/setup and @antv/setup + 4 imposter commit SHAs |
| 9 | Network connections | Active connections to C2 infrastructure (5 domains/IPs) |
| 10 | DNS cache | Prior resolution of attacker domains (4 domains) |
| 11 | Git branches | Dune-themed attacker branch naming pattern |
| 12 | Lifecycle scripts | Heuristic: bun run in preinstall/postinstall (installed packages) |
| 13 | Dead-drop C2 | firedalazer keyword and "Shai-Hulud" markers in git history |
| 14 | GitHub deps | Heuristic: github: dependencies pinned to commit SHA in optionalDeps |
Only @tanstack/router* and @tanstack/start* were affected. NOT affected: @tanstack/query*, @tanstack/table*, @tanstack/form*, @tanstack/virtual*, @tanstack/store.
| Package | Malicious versions | First safe version |
|---|---|---|
@tanstack/react-router | 1.169.5, 1.169.8 | 1.169.9 |
@tanstack/router-core | 1.169.5, 1.169.8 | 1.169.9 |
@tanstack/vue-router | 1.169.5, 1.169.8 | 1.169.9 |
@tanstack/solid-router | 1.169.5, 1.169.8 | 1.169.9 |
@tanstack/react-start | 1.167.68, 1.167.71 | 1.167.72 |
@tanstack/router-plugin | 1.167.38, 1.167.41 | 1.167.42 |
See the full advisory for all 42 packages.
All packages published by npm user atool ([email protected]) received malicious versions on May 19, 2026. High-impact packages include:
| Package | Monthly downloads |
|---|---|
size-sensor | 4.2M |
echarts-for-react | 3.8M |
@antv/scale | 2.2M |
timeago.js | 1.15M |
Plus 310+ packages primarily in the @antv/* scope (@antv/g2, @antv/g6, @antv/l7, @antv/s2, @antv/x6, @antv/f2, etc.), ai-figure, timeago-react, jest-canvas-mock, jest-date-mock, and others.
See the SafeDep writeup for the full list.
CRITICAL: Disable the dead-man's switch BEFORE revoking any tokens. The malware wipes
$HOMEif tokens are revoked while the daemon is active.
gh-token-monitor AND kitty-monitor) and remove LaunchAgent/systemd services.claude/router_runtime.js, .vscode/setup.mjs, ~/.local/share/kitty/cat.py, /var/tmp/.gh_update_state, etc.)node_modules and lockfiles, reinstall with --ignore-scriptsapi.masscan.cloud, filev2.getsession.org, git-tanstack.com, t.m-kosche.com)