William OGOU Cybersecurity Blog

Published

- 8 min read

The Silent Worm: TeamPCP Hijacks TanStack in "Mini Shai-Hulud" Attack

img of The Silent Worm: TeamPCP Hijacks TanStack in "Mini Shai-Hulud" Attack

With over 518 million cumulative monthly downloads across the affected libraries, the software supply chain is facing an unprecedented crisis. On May 11, 2026, the threat actor known as “TeamPCP” orchestrated a massive, self-spreading worm campaign targeting both the npm and PyPI ecosystems.

Dubbed “Mini Shai-Hulud,” this attack compromised foundational packages including TanStack, UiPath, Mistral AI, OpenSearch, and Guardrails AI. But what makes this breach terrifying isn’t just its scale it’s the tradecraft. The attackers successfully bypassed traditional authentication, extracted OIDC tokens directly from CI/CD runner memory, and published malicious packages that carry valid SLSA Build Level 3 provenance attestations.

Worse, the malware lays a devastating trap for incident responders: a dead-man’s switch that transforms the stealer into a wiper if you revoke your credentials too quickly. Here is the technical breakdown of how TeamPCP pulled off the attack of the year, and the exact steps you must take to sanitize your environment without triggering a localized wipe.

For the complete list of affected packages, see Wiz’s comprehensive analysis, which includes 170+ compromised npm and PyPI packages across multiple namespaces.

What to Remember

  • Valid SLSA Provenance: The compromised TanStack packages are the first documented npm worm to carry valid SLSA Build Level 3 attestations, proving that supply chain signatures are useless if the CI runner itself is poisoned.
  • The “Dead-Man’s Switch” Trap: The malware installs a daemon (gh-token-monitor) that polls GitHub every 60 seconds. Do not blindly revoke your tokens. If the token is revoked, the script executes rm -rf ~/ on your machine.
  • Advanced C2 Evasion: The attackers use the decentralized Session messenger network to exfiltrate data, bypassing traditional enterprise DNS blocklists.
  • OIDC Memory Extraction: The attackers didn’t steal long-lived npm tokens. They poisoned the GitHub Actions cache and extracted short-lived OIDC tokens directly from the /proc/<pid>/mem runner process.

The Anatomy of a Perfect Worm: SLSA Bypass & Cache Poisoning

Most supply chain attacks rely on stealing a developer’s long-lived personal access token (PAT). TeamPCP didn’t bother. They went after the build pipeline itself.

The compromise of the @tanstack ecosystem (which includes the immensely popular @tanstack/react-router) relied on a highly sophisticated chained GitHub Actions attack.

  1. The Poisoned Pull Request: The attacker forked the TanStack/router repository (hiding it under a renamed account) and submitted a pull request.
  2. The pull_request_target Exploit: The repository used the dangerous pull_request_target workflow trigger. This executed the workflow in the context of the base repository but checked out the attacker’s malicious code.
  3. Cache Poisoning: The malicious PR poisoned the GitHub Actions cache with a tampered pnpm store.
  4. Memory Extraction: When legitimate maintainers later merged code into main, the release workflow restored the poisoned cache. The attacker-controlled binaries executed and dumped the GitHub Actions runner’s process memory (/proc/<pid>/mem) to extract the temporary OIDC token.

Because the attacker used the pipeline’s legitimate OIDC permissions to “mint” a short-lived publish token, the resulting malicious packages were signed with valid SLSA Build Level 3 provenance attestations. To the outside world, and to automated security scanners, these packages looked perfectly legitimate.

The Infection Vector and Triple-Threat Exfiltration

Once a developer runs npm install on a compromised package (like the 84 affected TanStack versions or the UiPath variants), a lifecycle hook (prepare or preinstall) executes a bundled setup.mjs script. This downloads the Bun runtime and executes an obfuscated, 2.3MB JavaScript payload (router_init.js).

This payload is a comprehensive credential stealer targeting AWS IMDSv2, HashiCorp Vault, Kubernetes service accounts, and cryptocurrency wallets. But its exfiltration architecture is what makes it unique. TeamPCP uses three redundant channels:

  1. Decentralized Evasion (Session Protocol): The primary exfiltration route sends data to filev2.getsession[.]org. Because Session is a privacy-focused, decentralized messaging service, it is rarely blocked by enterprise firewalls.
  2. Typosquat Fallback: It attempts to phone home to git-tanstack[.]com.
  3. GitHub API Dead Drops: Using stolen GitHub tokens, the malware uses the GraphQL API to create new, Dune-themed repositories (description: "Shai-Hulud: Here We Go Again") on the victim’s account, committing the encrypted stolen credentials as files.

⚠️ The Wiper Trap: Do Not Revoke Tokens Immediately

TeamPCP knows that the standard Incident Response (IR) playbook dictates immediately revoking compromised credentials. To counter this, they weaponized the IR process itself.

If the malware finds a valid GitHub token with repository write access, it establishes persistence by installing a daemon called gh-token-monitor.

This daemon polls the api.github.com/user endpoint every 60 seconds using the stolen token. If a developer revokes the token from their GitHub dashboard, the API returns a 401 Unauthorized error. The daemon interprets this as a kill signal and immediately triggers a destructive routine: rm -rf ~/ (wiping the developer’s home directory).

Step-by-Step Remediation Walkthrough

If you suspect your machine has installed a compromised version of @tanstack, @uipath, or @mistralai, you must follow this exact order of operations to avoid the wiper.

Step 1: Isolate the Machine from the Network Disconnect from Wi-Fi or unplug the ethernet cable. This stops the daemon from communicating with GitHub and receiving a 401 error while you work.

Step 2: Hunt for and Kill the Persistence Hooks Check for the gh-token-monitor daemon and delete it. Command (macOS):

   launchctl unload ~/Library/LaunchAgents/com.user.gh-token-monitor.plist
rm ~/Library/LaunchAgents/com.user.gh-token-monitor.plist

Command (Linux):

   systemctl --user stop gh-token-monitor.service
rm ~/.config/systemd/user/gh-token-monitor.service

Why: You must kill the dead-man’s switch before invalidating the token.

Step 3: Audit IDE Directories for Runtime Artifacts The malware establishes secondary persistence hooks in your IDE folders to re-infect you upon reboot. Command:

   find ~/.vscode ~/.claude -name "router_runtime.js" -o -name "setup.mjs" -type f -delete

Step 4: Rotate Credentials Only after steps 1-3 are complete should you log into your cloud providers (from a different, clean device) and rotate your AWS keys, GitHub tokens, npm publish tokens, and Kubernetes service accounts.

The Python PyPI Variant: Geofenced Destruction

While the npm ecosystem suffered the brunt of the attack, PyPI was not spared. Packages like [email protected] and [email protected] were infected.

The Python variant executes upon import. Instead of a massive obfuscated file, it contains 13 lines of code that download a payload from git-tanstack[.]com/tmp/transformers.pyz.

This variant includes highly specific, geofenced logic:

  • Russian Language Bypass: If the system is configured for the Russian language, the malware exits silently.
  • Geofenced Wiper: If the system timezone and language indicate it is located in Israel or Iran, the malware invokes random.randint(1,6). If it rolls a 2, it plays an mp3 file at full volume and attempts to run rm -rf / to destroy the entire file system.

Lessons Learned: Redefining Supply Chain Defense

  • Lesson 1: pull_request_target is a loaded gun. TanStack’s compromise proves that executing workflows in the context of the base repo while checking out untrusted fork code leads directly to cache poisoning and OIDC theft. What should happen: Never use pull_request_target unless strictly necessary, and never combine it with an untrusted code checkout.
  • Lesson 2: SLSA is only as secure as the runner. The attackers achieved valid SLSA Level 3 attestations because they hijacked the legitimate identity of the runner. What should happen: Organizations must monitor behavioral anomalies during builds, not just cryptographic signatures after the fact.
  • Lesson 3: Blind revocation is dangerous. Threat actors are actively anticipating standard IR playbooks. What should happen: IR teams must analyze the malware’s local behavior (identifying dead-man’s switches) before initiating mass credential revocation.

Conclusion

The “Mini Shai-Hulud” campaign by TeamPCP is a masterclass in modern software supply chain exploitation. This attack follows a series of high-profile compromises attributed to the same actor, including the hijacking of Trivy and LiteLLM. We are also seeing the evolution of these tactics in the emerging Shai-Hulud 2.0 recursive infection models.

By combining GitHub Actions cache poisoning, OIDC memory extraction, decentralized C2 exfiltration, and a punitive wiper script, they have elevated the baseline of what defenders must protect against.

Security teams can no longer rely solely on static analysis or package signatures. You must enforce strict egress filtering on your CI/CD runners, disable automatic preinstall script execution, and actively monitor the runtime behavior of your build environments.

To further enhance your cloud security and implement Zero Trust, contact me on LinkedIn Profile or [email protected].

Indicators of Compromise (IOCs)

Security teams should use these IOCs to detect and respond to Mini Shai-Hulud infections:

File Hashes

FileSizeHash TypeHash Value
router_init.js2,341,681 bytesSHA256ab4fcadaec49c03278063dd269ea5eef82d24f2124a8e15d7b90f2fa8601266c
router_init.js2,339,346 bytesSHA2562ec78d556d696e208927cc503d48e4b5eb56b31abc2870c2ed2e98d6be27fc96
router_init.js2,339,346 bytesSHA1e7d582b98ca80690883175470e96f703ef6dc497
setup.mjs5,047 bytesSHA2562258284d65f63829bd67eaba01ef6f1ada2f593f9bbe41678b2df360bd90d3df
setup.mjs5,047 bytesSHA112f35b1081b17d21815b35feb57ab03d02482116
Trojanized tarballSHA2561e8538c6e0563d50da0f2e097e979ebd5294ce1defe01d0b9fe361ba3bed1898
opensearch_init.jsSHA1820fa07a7328b6cf2b417078e103721d4d8f2e79

Network Indicators

TypeIndicatorPurpose
Domaingit-tanstack.comPrimary C2 infrastructure
Payload URLgit-tanstack.com/tmp/transformers.pyzPyPI variant payload delivery
Session Seed Nodeseed1.getsession.orgDecentralized message routing
Session Seed Nodeseed2.getsession.orgDecentralized message routing
Session Seed Nodeseed3.getsession.orgDecentralized message routing
Session File Serverfilev2.getsession.orgCredential exfiltration endpoint
Session Recipient ID05f9e609d79eed391015e11380dee4b5c9ead0b6e2e7f0134e6e51767a87323026Attacker’s decentralized inbox
C2 IP Address83.142.209.194PyPI variant exfiltration server

System Indicators

IndicatorLocationPlatform
gh-token-monitor~/Library/LaunchAgents/com.user.gh-token-monitor.plistmacOS
gh-token-monitor~/.config/systemd/user/gh-token-monitor.serviceLinux
router_runtime.js~/.vscode/ or ~/.claude/IDE persistence
tanstack_runner.js~/.vscode/ or ~/.claude/IDE persistence
Preinstall hookpackage.jsonnode setup.mjs
Git dependencypackage.jsongithub:tanstack/router#79ac49eedf774dd4b0cfa308722bc463cfe5885c

Frequently Asked Questions (FAQ)

What is the Mini Shai-Hulud supply chain attack?

It is a massive supply chain compromise by the threat actor TeamPCP, infecting over 170 npm and PyPI packages. It operates as a self-spreading worm that steals credentials and leverages compromised OIDC tokens to publish more malicious packages.

How did TeamPCP bypass SLSA provenance checks?

The attackers used a GitHub Actions 'pull_request_target' exploit to poison the build cache. They then extracted OIDC tokens from the runner's memory to mint short-lived publish tokens, resulting in malware signed with legitimate SLSA Level 3 attestations.

Why should I wait before revoking my GitHub tokens if compromised?

The malware installs a dead-man's switch daemon ('gh-token-monitor') that checks if your token is valid every 60 seconds. If it detects you have revoked the token, it immediately executes a destructive command to wipe your home directory.

How does the malware communicate with its C2 servers?

To evade traditional DNS blocking, the malware uses a triple-threat architecture: typosquat domains (git-tanstack[.]com), the decentralized Session messaging network (*.getsession.org), and GitHub API dead drops via stolen tokens.

What makes the Python variant (like Mistral AI) different?

The PyPI payload executes on 'import' and downloads a remote Python artifact. It features geofenced logic that bypasses Russian-language systems and includes a 1-in-6 chance of executing a destructive wiper if the machine is located in Israel or Iran.


William OGOU

William OGOU

Need help implementing Zero Trust strategy or securing your cloud infrastructure? I help organizations build resilient, compliance-ready security architectures.