Mini-Shai Hulud Poisons TanStack Cache for NPM Worm Spread
Better Stackgo watch the original →
the gist
Attacker forked TanStack Router, used pull_request_target to poison pnpm cache in bundle workflow, restored malicious cache in release action to publish 84 infected versions across 42 packages via OIDC; malware steals creds, sets deadman wipe, self-propagates.
The Breakthrough
The attacker chained GitHub Actions cache poisoning through a renamed fork's pull_request_target workflow, injecting a malicious pnpm store that TanStack's release action later restored, enabling OIDC-based publishes of 84 malicious versions across 42 packages.
What Actually Worked
- The malware injects
routerinit.js(or equivalent) and a fake optional dependency tohttps://github.com/TanStack/router#commit-from-fork, where apreparelifecycle script runsbun run taskr runner.js && exit 1to execute payload then fail silently. - The script checks if already running, forks a detached background process, and exits the parent to avoid npm install log traces.
- It copies itself to Claude Code hooks directory and configures Claude settings to re-run on Claude Code use; duplicates in VS Code taskrunner for workspace auto-run persistence; sets OS service "GitHub token monitor".
- It scrapes GitHub Actions runner memory for secrets (including masked), inserts fake CodeQL workflow to exfil repo secrets; grabs AWS env/config/IMDSv2/ECS metadata; Kubernetes service account tokens/certs for in-cluster API; HashiCorp Vault env/tokens then retrieves all secrets via K8s access; workstation targets include SSH keys, npm/git creds, shell history, cloud creds, crypto keys, Signal/Slack/Discord files, Claude session history; exfils via Session Messenger or GitHub dead-drop branches named after Dune references.
- The "GitHub token monitor" service re-exfils tokens every minute, checks validity, and runs
rm -rfon user directory if invalid; creates NPM token with description "if you revoke this token we will wipe the computer of the owner". - For propagation, scans accessible NPM packages via stolen tokens (no 2FA), adds/publishes infected versions; in CI/CD, requests OIDC JWT from GitHub, exchanges for short-lived NPM publish token via trusted publishing, bundles
routerinit.jsinto package tarball, adds malicious optional dep, publishes aslatest. - TanStack infection: Created renamed fork of TanStack Router, added
skip CI-prefixed commit poisoning pnpm cache via public pnpm-lock.yaml formula in bundleize workflow (pull_request_target grants base repo cache/token access); reset branch to main (noop PR), closed/deleted; 8 hours later, unrelated main merge triggers release, restores poisoned cache, runs attacker code to OIDC-publish despite test failures.
Context
The "Mini-Shai Hulud" NPM worm (fourth variant) targeted TanStack, UiPath, Mistral AI, Guardrails AI, and 160+ packages. It shifts supply chain attacks from stealing maintainer tokens to exploiting CI/CD trust boundaries like caches, pull_request_target, and OIDC, producing signed packages with valid provenance from real workflows. Developers must check for compromise via linked blogs, as deadman switch risks data loss on credential rotation without isolation.
Notable Quotes
- "if you revoke this token we will wipe the computer of the owner"
- Python variant checks machine language: Russian → stops; Israel/Iran → 1/6 chance of wipe + MP3 playback.
Content References
(none directly quoted; promo links and socials omitted)