
Mini Shai-Hulud Worm Compromises TanStack, Mistral AI, Guardrails AI & More Packages
The Hacker News details the "Mini Shai-Hulud" campaign by threat actor TeamPCP, which compromised npm and PyPI packages from TanStack, UiPath, Mistral AI, OpenSearch and Guardrails AI via a chained GitHub Actions attack (pull_request_target abuse, cache poisoning, OIDC token extraction), now tracked as CVE-2026-45321 (CVSS 9.6). The worm mints npm publish tokens directly from stolen OIDC credentials to self-propagate — the first documented case of a worm producing validly SLSA Build Level 3-attested malicious packages — and deploys an obfuscated credential stealer with IDE persistence hooks, a GitHub Actions secret-exfiltration workflow, and a dead-man's-switch that runs "rm -rf" if its rogue npm token is revoked. Over 170 packages and 400+ attacker-controlled repos have been identified across npm and PyPI, with findings credited to Aikido Security, Endor Labs, SafeDep, Socket, StepSecurity, Snyk, Wiz and Microsoft.
What it is
The Mini Shai-Hulud worm (attributed to TeamPCP, tracked as CVE-2026-45321, CVSS 9.6) with the specific indicators, package versions, and one operational constraint the summary omits. The summary establishes the campaign, the OIDC-minting mechanism, and the SLSA-attestation novelty — this document carries the IOCs, the root-cause misconfiguration, and the incident-response ordering rule.
Root cause you can actually fix
The TanStack compromise worked because the OIDC trusted-publisher config granted trust at the repository level rather than scoped to a specific protected branch and workflow file. An orphaned commit in a fork triggered the legitimate TanStack/router workflow surface, which was then able to request a valid short-lived npm publish token. If your trusted publishing is repo-scoped rather than branch/workflow-scoped, you have the same exposure. The propagation step also depends on finding a publishable npm token with bypass_2fa set to true.
Critical IR ordering constraint
The dead-man's switch polls api.github.com/user every 60 seconds; the malware's npm token carries the description IfYouRevokeThisTokenItWillWipeTheComputerOfTheOwner. Revoking that token from the npm dashboard triggers rm -rf ~/, turning the host into a wiper. Do not revoke the token before isolating and imaging the system. This inverts normal "revoke credentials first" response.
Indicators of compromise
- Exfil channels:
filev2.getsession[.]org(Session Protocol, unlikely to be blocked in enterprises),api.masscan[.]cloud(Actions secrets), typosquatgit-tanstack[.]com, and IP83.142.209[.]194(PyPI stealer download) - Dead-drop repos committed under author
claude@users.noreply.github.com; all attacker repos contain the stringShai-Hulud: Here We Go Again(400+ such repos) - npm payload file:
router_init.js; PyPI payload writes/tmp/transformers.pyzand runs it withpython3without integrity verification - IDE persistence hooks in Claude Code and VS Code; a
gh-token-monitorservice re-exfiltrates GitHub tokens
Affected versions (confirmed)
guardrails-ai@0.10.1(PyPI) — executes on import, not installmistralai@2.4.6(PyPI)@opensearch-project/opensearch@3.5.3, 3.6.2, 3.7.0, 3.8.0@squawk/mcp@0.9.5,@squawk/weather@0.5.10,@squawk/flightplan@0.5.6@tallyui/connector-medusa@1.0.1–1.0.3,@tallyui/connector-vendure@1.0.1–1.0.3- TanStack: 42 packages, 84 versions
Delivery differs by cluster
flowchart TD
A[Compromised package] --> B{Cluster}
B -->|TanStack| C[JS file in tarball + optional dep to GitHub package]
C --> D[prepare hook runs payload via Bun]
B -->|Mistral npm| E[package.json preinstall hook]
E --> F[node setup.mjs downloads Bun, runs same JS malware]
B -->|PyPI| G[Download stealer from remote server]
G --> H[Geofenced: 1-in-6 rm -rf / in Israel/Iran, skips Russian-language envs]The TanStack cluster hides its JS payload in the tarball and pulls execution through an optional GitHub-hosted dependency's prepare hook (Bun runtime), whereas Mistral's npm packages use the older preinstall → node setup.mjs route.
Caveats
TanStack states no npm tokens were stolen and its publish workflow was not compromised — the abuse was purely OIDC-token minting from a hijacked workflow run. The PyPI variants "operate notably differently" from the npm JavaScript malware (per Wiz), so npm-focused detections won't cover the Python packages.
Organisations named here
- pull_request_target
- Shai-Hulud
CVEs named here
- CVE-2026-45321
Technologies named here
- router_init.js
- TanStack/router and TanStack ecosystem packages
- UiPath packages
- gh-token-monitor
- Session Protocol / getsession.org infrastructure
- Mistral AI - mistralai@2.4.6
- Aikido Security
- Mistral AI npm packages
- Endor Labs
- OpenSearch - @opensearch-project/opensearch
- Guardrails AI - guardrails-ai@0.10.1
- SafeDep
- @squawk/mcp
- Socket
- StepSecurity
- @squawk/weather
- @squawk/flightplan
- Snyk
- OX Security
- @tallyui/connector-medusa
- @tallyui/connector-vendure
- Wiz
- microsoft
- DraftLab packages
- Claude Code and Microsoft Visual Studio Code
- Upwind
- GitHub Actions / GitHub
- npm
- PyPI
- GitHub Actions
- tanstack
- SLSA
- OIDC
Techniques named here
- Trusted publishing / OIDC token abuse
- GitHub Actions cache poisoning
- pull_request_target trigger abuse
- Runtime memory extraction of OIDC token
- Orphaned commit staging in GitHub fork
- SLSA provenance abuse
- Worm self-propagation via npm tokens
- Optional dependency / prepare lifecycle hook execution
- Preinstall hook execution
- Dead-man's switch / destructive wiper trigger
- Geofenced destructive payload
- Malicious GitHub Actions workflow injection
- Redundant exfiltration channels
- Execution on package import
Threat actors named here
- TeamPCP
- Mini Shai-Hulud
Related in Supply Chain


