← EasyTool.me

TanStack npm Supply Chain Attack — Mini Shai-Hulud Worm Returns

Published: 2026-05-12 Reading: 6 min Security / Supply Chain Attack

What Happened

On May 11, 2026, a self-propagating worm known as Mini Shai-Hulud compromised the TanStack npm ecosystem — one of the most widely used React routing libraries with millions of weekly downloads. The attack injected a 2.3 MB obfuscated credential-stealing payload into 40+ @tanstack packages and published the malicious versions through the project's own GitHub Actions release pipeline using hijacked OIDC tokens.

What makes this incident historic: it is the first documented self-spreading npm worm that carries valid SLSA provenance attestations. The packages look legitimate because they are published by the real pipeline — the worm inherited TanStack's trusted publisher identity.

The attack was first disclosed by StepSecurity via their OSS Package Security Feed, which detected the compromised releases in real time. A GitHub issue (#7383) was filed to notify maintainers, and the story quickly reached the Hacker News front page.

How the Attack Works

Step 1: Fork and Stage the Payload

The attacker created a fork of TanStack/router on May 10, 2026 and pushed a single commit (79ac49ee) containing a fake @tanstack/setup package. This package had a prepare lifecycle hook that runs bun run tanstack_runner.js && exit 1 — the && exit 1 is deliberate, causing the optional dependency to "fail" gracefully while the payload has already executed.

Step 2: Inject Into Published Packages

Two modifications were made to each compromised package:

The result: compromised tarballs were 3.7x larger than clean versions (905 KB vs 190 KB), with 23 extra files.

Step 3: Publish via Legitimate Pipeline

The malicious packages carried valid SLSA provenance attestations tied to the real TanStack Release workflow. The attacker exploited the workflow's ambient id-token: write OIDC token to publish directly to npm — bypassing the workflow's own publish step, even though the "Run Tests" step had failed.

Critical insight: SLSA provenance confirms which pipeline produced the artifact, not whether the pipeline was behaving as intended. A compromised build step can produce a validly-attested but malicious package.

The Payload: What It Steals

The router_init.js payload uses multiple layers of obfuscation:

The payload contains 10 dedicated collector classes that harvest secrets from multiple sources. It reads GitHub Actions environment variables (GITHUB_WORKFLOW_REF, GITHUB_REPOSITORY, etc.) to identify high-value targets. It imports child_process, fs, crypto, and os — giving it arbitrary command execution, file system access, and cryptographic signing capabilities.

Stolen credentials are exfiltrated over HTTPS (port 443) to attacker-controlled infrastructure using a buffered dispatch system with multiple fallback senders.

Self-Propagation: The Worm Mechanism

The most dangerous aspect of Mini Shai-Hulud is its autonomous spreading. After collecting tokens, the worm iterates over discovered GitHub tokens and uses them to:

  1. Authenticate against the npm registry or GitHub API
  2. Identify other packages the token has write access to
  3. Inject the same malicious payload into those packages
  4. Publish new compromised versions

This propagation loop explains why the attack spread beyond TanStack to packages like @uipath, @draftauth, @draftlab, @taskflow-corp, and @tolka — the worm followed the stolen credentials wherever they led.

Affected Packages (Partial List)

The attack hit 40+ packages across multiple organizations:

@tanstack ecosystem — react-router, router-core, react-start, solid-router, vue-router, history, router-plugin, and dozens more. Each package received two compromised versions (a "double-tap" pattern).

Other organizations — @uipath (8 packages including agent.sdk, filesystem, admin-tool), @draftauth (client, core), @draftlab (auth, auth-router, db), @taskflow-corp/cli, and @tolka/cli.

The full list is continuously updated on the StepSecurity OSS Security Feed.

Am I Affected?

Check Your Lockfiles

grep "@tanstack/" package-lock.json | grep -v node_modules
grep -E "(draftlab|draftauth|taskflow-corp|tolka)" package-lock.json pnpm-lock.yaml yarn.lock 2>/dev/null

Cross-reference resolved versions against the compromised versions listed by StepSecurity.

Check for the Malicious File

find node_modules -name "router_init.js" -type f 2>/dev/null
grep -r "@tanstack/setup" node_modules/*/package.json 2>/dev/null

Detection Signals

Recovery Steps

For Individual Developers

  1. Pin to safe versions — downgrade to the last clean version for each affected package
  2. Delete and reinstallrm -rf node_modules && npm install
  3. Rotate credentials — any npm tokens, GitHub PATs, and cloud API keys accessible on that machine
  4. Check ~/.npmrc — the worm reads home directory secrets; review and rotate stored tokens

For CI/CD Environments (Critical)

  1. Rotate all CI secrets immediately — GitHub tokens, npm tokens, cloud provider credentials, and any other secrets available in the workflow environment
  2. Audit GitHub Actions runs — review runs after 2026-05-11T19:20Z for unexpected npm publish events
  3. Check for downstream propagation — if any of your packages were published during a CI run that installed a compromised version, those published versions may also be compromised
  4. Review npm access tokens — run npm token list and revoke unrecognized tokens

Defending Against CI/CD Worm Attacks

Indicators of Compromise

SHA-256 hashes:

Attacker infrastructure:

Summary

The Mini Shai-Hulud attack exposes a fundamental gap in the npm ecosystem's trust model. Provenance attestations prove where a package was built, not what was built. A worm that compromises a CI/CD pipeline inherits the pipeline's entire identity — its OIDC tokens, its SLSA signatures, its trusted publisher status. From the registry's perspective, the malicious publish is indistinguishable from a legitimate one.

Key takeaways:

Sources: StepSecurity — Mini Shai-Hulud Is Back | GitHub Issue #7383 | Hacker News Discussion