CriticalSupply chainPatch available

TanStack to Nx Console to GitHub: one poisoned npm install led to ~3,800 stolen internal repos (CVE-2026-45321, CVE-2026-48027)

Poisoned TanStack packages stole an Nx developer’s GitHub token. A trojaned Nx Console release then hit GitHub and Grafana. Check installs, rotate tokens.

Published
Updated
Fixed in
Patched @tanstack/* releases per GHSA-g7cv-rxg3-hmpx; Nx Console 18.100.0 or later
Exploitation
Yes. Both CVEs added to CISA’s Known Exploited Vulnerabilities catalogue on 27 May 2026, flagged for known ransomware use

Live scores

CVE-2026-45321
EPSS
0.033
some chance of attack soon
VEDAS
0.973
strong exploit evidence
On CISA KEV
Yes, since 2026-05-27
Detection rule
None yet
EPSS (chance of attack)
100.1CVE-2026-45321 EPSS over time2026-082026-11-01
VEDAS (exploit evidence)
100.9CVE-2026-45321 VEDAS over time2026-082026-11-01

Thin horizontal line: the “likely” (EPSS 0.10) or “strong” (VEDAS 0.90) threshold. Shaded “no data” areas are periods when cve-scores did not publish.

Live scores

CVE-2026-48027
EPSS
0.018
some chance of attack soon
VEDAS
0.522
some exploit evidence
On CISA KEV
Yes, since 2026-05-27
Detection rule
None yet
EPSS (chance of attack)
100.1CVE-2026-48027 EPSS over time2026-082026-11-01
VEDAS (exploit evidence)
100.9CVE-2026-48027 VEDAS over time2026-082026-11-01

Thin horizontal line: the “likely” (EPSS 0.10) or “strong” (VEDAS 0.90) threshold. Shaded “no data” areas are periods when cve-scores did not publish.

What happened

This is a chain of four compromises, each one paid for with credentials stolen in the last.

1. TanStack, 11 May 2026 (CVE-2026-45321)

Between about 19:20 and 19:26 UTC, 84 malicious versions of 42 @tanstack/* packages were published to npm, two per package (TanStack advisory). Only the Router and Start repository was affected. Query, Table, Form, Virtual, Store and the other TanStack libraries were not (TanStack post-mortem).

No maintainer token was stolen. The attacker chained three weaknesses in TanStack’s GitHub Actions setup (TanStack post-mortem):

  1. A pull_request_target workflow built code from a fork pull request inside the main repository’s context.
  2. That build wrote a poisoned pnpm store into the shared GitHub Actions cache, which the release workflow later restored.
  3. When the release workflow ran, the attacker’s code read the runner’s memory, took its OIDC token and published straight to npm under TanStack’s trusted-publisher identity.

Each bad version added an optionalDependencies entry, "@tanstack/setup": "github:tanstack/router#79ac49ee...", that pulled in an orphan commit. Its prepare script ran a 2.3 MB obfuscated router_init.js during npm, pnpm or yarn install. The payload stole AWS, GCP, Kubernetes, Vault, npm and GitHub credentials (including gh CLI config) and SSH keys, sent them over the Session file-upload network, and republished the victim’s own npm packages with the same injection (TanStack advisory). The advisory rates it CVSS 9.6.

2. Nx Console, 18 May 2026 (CVE-2026-48027)

At 20:43 UTC on 11 May, an Nx contributor ran pnpm install in another project and resolved the malicious @tanstack/zod-adapter@1.166.15. The payload took the contributor’s GitHub CLI OAuth token and used it within 74 seconds (Nx post-mortem). That repository had a 7-day minimum-release-age in .npmrc, but its pinned pnpm 10.14 silently ignored the setting, which needs pnpm 10.16 or later. The malicious version was 77 minutes old.

A week later, on 18 May at 12:30 UTC, the attacker used the stolen access to publish Nx Console 18.95.0 to the Visual Studio Marketplace and Open VSX. It was live for about 18 and 36 minutes respectively (Nx Console advisory). Marketplace counts show 28 and 41 downloads, but Nx saw about 6,000 activations in its own analytics and believes the real impact is far higher, because the extension auto-updates. The payload harvested Vault, npm, AWS, GitHub, 1Password and Docker credentials and private keys, and installed a Python backdoor. The Nx CLI, @nx/* plugins and Nx Cloud were not affected (Nx post-mortem).

3. GitHub, 18 to 20 May 2026

On 18 May GitHub detected and contained a compromised employee device, infected by a “poisoned VS Code extension”; its post links the Nx Console advisory. GitHub says the attacker exfiltrated GitHub-internal repositories only. The attacker claims about 3,800 repositories, which GitHub calls “directionally consistent” with its investigation. GitHub found no evidence of impact to customer data outside those repositories, though some internal repositories hold excerpts of support interactions (GitHub). GitHub rotated its GitHub Enterprise Server signing key as a precaution. GitHub does not name the attacker. Tenable reports that GitHub was responding to claims made by TeamPCP (Tenable), the group behind the Trivy and LiteLLM compromises.

4. Grafana Labs, 11 to 17 May 2026

The TanStack payload ran on Grafana’s self-hosted runners at 19:21 UTC on 11 May. Grafana rotated the credentials it knew about, but “we missed one”. On 14 May the attacker used a leaked grafana-delivery-bot identity to make a malicious commit and clone Grafana’s repositories, then demanded a ransom on 15 May. Grafana refused to pay. It says source code was downloaded but not altered, that Grafana Cloud and customer production systems were not touched, and that Mandiant found no evidence of code tampering (Grafana).

CISA added both CVEs to its Known Exploited Vulnerabilities catalogue on 27 May 2026 and marked both as known to be used in ransomware campaigns (CISA KEV).

Am I affected?

TanStack. The bad versions were all published on 11 May 2026. The full list of 84 versions, with the patched release for each, is in the TanStack advisory. Some common ones:

PackageBad versionsPatched
@tanstack/react-router1.169.5, 1.169.81.169.9
@tanstack/router-core1.169.5, 1.169.81.169.9
@tanstack/react-start1.167.68, 1.167.711.167.72
@tanstack/router-plugin1.167.38, 1.167.411.167.42
@tanstack/vue-router1.169.5, 1.169.81.169.9
@tanstack/solid-router1.169.5, 1.169.81.169.9
@tanstack/history1.161.9, 1.161.121.161.13
@tanstack/zod-adapter1.166.12, 1.166.151.166.16
bash
# The injected git dependency is the clearest marker in any lockfile
grep -nE '@tanstack/setup|tanstack/router#79ac49ee' package-lock.json yarn.lock pnpm-lock.yaml bun.lock 2>/dev/null

# The payload inside installed packages
find . -path '*node_modules/@tanstack/*' -name router_init.js 2>/dev/null

# Router and Start packages you resolve, to compare against the advisory table
npm ls --all 2>/dev/null | grep -E '@tanstack/(.*router|.*start|history|.*adapter|virtual-file-routes)'

Also check CI: any pipeline that installed @tanstack/* between 19:20 and 19:30 UTC on 11 May 2026 should be treated as compromised (TanStack advisory).

Nx Console. The extension ID is nrwl.angular-console. Check every editor that loads VS Code extensions:

bash
code --list-extensions --show-versions 2>/dev/null | grep -i angular-console
cursor --list-extensions --show-versions 2>/dev/null | grep -i angular-console

# Persistence left by the 18.95.0 payload (macOS and Linux)
ls -la ~/.local/share/kitty/cat.py ~/Library/LaunchAgents/com.user.kitty-monitor.plist \
  /var/tmp/.gh_update_state 2>/dev/null
ps aux | grep -E '[c]at\.py'

A version above 18.95.0 today does not clear you: auto-update could have installed 18.95.0 during the window and replaced it later. Any cat.py process, or a process with __DAEMONIZED=1 in its environment, is a confirmed infection. On Windows, look for %USERPROFILE%\.local\share\kitty\cat.py, %TEMP%\.gh_update_state and an unexpected %USERPROFILE%\.bun\bin\bun.exe (Nx Console advisory).

GitHub. GitHub Enterprise Cloud customers need do nothing. GitHub Enterprise Server admins must rotate the GPG public key used to verify upgrade packages; otherwise future upgrades fail with “The file provided is not a valid GitHub Enterprise Server package” (GitHub).

What to do now

  1. Rotate everything on affected hosts. GitHub tokens (run gh auth logout and log in again, and revoke the old OAuth token in GitHub settings), npm tokens, cloud keys, Vault tokens, 1Password sessions and SSH keys. Then review cloud and GitHub audit logs for use of the old credentials.
  2. Reinstall TanStack cleanly. Upgrade each package to the patched version in the advisory, delete node_modules and the lockfile entries, and reinstall. TanStack says every version now on npm is safe (TanStack post-mortem).
  3. Clean Nx Console hosts. Update to 18.100.0 or later, kill cat.py processes, run launchctl unload ~/Library/LaunchAgents/com.user.kitty-monitor.plist on macOS, then delete the persistence files (Nx Console advisory). On Linux, check /etc/sudoers for changes.
  4. GitHub Enterprise Server: rotate the GPG key with GitHub’s script, verifying its checksum first. Run it as your admin user and again with sudo; on HA or cluster setups, prefix each step with ghe-cluster-each -- (GitHub):
bash
curl -fsSL https://enterprise.github.com/security/2026-05-24/rotate-gpg.sh -o rotate-gpg.sh
shasum -a 256 rotate-gpg.sh   # expect 3009bf5cdef034e153008cc375a05ac0bdbb1a2a325b22adb300c028e3766b43
chmod ug+x ./rotate-gpg.sh
./rotate-gpg.sh
sudo ./rotate-gpg.sh
  1. Make your release-age delay real. If you set minimum-release-age in pnpm, pin packageManager to pnpm 10.16 or later and fail CI on older versions. Nx’s delay was configured but silently ignored (Nx post-mortem).
  2. Fix your own workflows. Never let a pull_request_target workflow build fork code, and never let it share a cache with your release workflow. Require a second person to approve any release.
  3. Rotate completely. Grafana’s breach came from one token missed in an otherwise thorough rotation. List every token a compromised host or runner could reach before revoking, and confirm each is dead.

Why this is part of the Vulnpocalypse

Each link in this chain was a developer tool doing its normal job: a CI cache, a trusted-publisher token, a gh login, an auto-updating editor extension. A single pnpm install on one contributor’s laptop reached GitHub’s own source code a week later. Grafana rotated quickly and still lost its repositories to one missed token. The lesson is that a developer’s credentials are production credentials, and incident response has to be complete, not just fast.

A note on the “Mini Shai-Hulud” name

Several vendors call the TanStack compromise part of the “Mini Shai-Hulud” campaign. Tenable says that campaign has been active since late April 2026 (Tenable), and Grafana’s own review uses the name for the 11 May attack (Grafana). Sonatype later applied the same name to an August 2026 wave in the keyv and cacheable packages (Sonatype). See our Shai-Hulud advisory for the wider worm family.

Sources