Mallory pivots from this family to the IOCs, detections, and named campaigns that touch your stack, and pages you when something new lands.
1 CVE Mallory has correlated with this family across public research and vendor advisories. Each row links to the full Mallory page for that vulnerability.
Inside the payload: router_init.js The 2.3 MB router_init.js file was smuggled into each compromised tarball's root...
1 distinct threat actor attributed by public researchers. Open in Mallory to see the full evidence chain and overlapping campaigns.
Inside the payload: router_init.js The 2.3 MB router_init.js file was smuggled into each compromised tarball's root...
27 distinct techniques documented for this family, organized by ATT&CK tactic.
For each target package, bundles a copy of router_init.js into the tarball (.tgz, tar.zst). Publishes the modified package using the ambient OIDC token of the host CI workflow.
On May 11, 2026, an attacker published 84 malicious package versions across 42 @tanstack/* npm packages in under six minutes, distributing credential-stealing malware through one of the JavaScript ecosystem's most widely used library families.
Because the repository's OIDC trusted publisher configuration granted trust at the repository level rather than scoped to a specific protected branch and workflow file, the workflow run triggered by that commit was able to request a valid short-lived npm publish token.
.vscode/tasks.json — task with "runOn": "folderOpen" to fire when the workspace is reopened.
Malicious versions... include Trojanized JavaScript and Python code leveraging preinstall/import hooks, Bun runtime stages...
In npm projects, malicious code can run automatically during dependency installation through package lifecycle scripts... It includes a malicious JSON configuration file that executes setup.mjs... the loader runs router_init.js, which contains the main obfuscated malware payload.
In the SAP wave, the compromised packages added a preinstall hook that ran setup.mjs... This wave uses a slightly different route... That Git dependency contains a prepare script: "scripts" : { "prepare" : "bun run tanstack_runner.js && exit 1" } This is the trick. npm runs lifecycle scripts for Git dependencies during installation. | In the SAP wave, the compromised packages added a preinstall hook that ran setup.mjs... This wave uses a slightly different route... That Git dependency contains a prepare script: "scripts" : { "prepare" : "bun run tanstack_runner.js && exit 1" }
When npm resolves a github: dependency, it clones the referenced commit and runs lifecycle hooks — including prepare — automatically. This caused tanstack_runner.js to execute on every developer machine or CI runner that installed any of the 84 affected packages.
The primary malicious file, router_init.js, is a massive 2.3 MB single-line JavaScript file. To evade detection ... it utilizes three distinct layers of cryptographic defense ...
The trailing exit 1 is deliberate — npm logs the install as a script failure rather than a script success, suppressing attention while the payload has already run.
The actual functional logic of the worm ... is stored as eleven secondary payloads encrypted with AES-256-GCM. These blobs are only decrypted and decompressed using the Bun runtime at the final stage of execution.
Machines with Bun already installed also trigger an early-exit in the payload's hasCommand("bun") check.
In the SAP wave, the compromised packages added a preinstall hook that ran setup.mjs... This wave uses a slightly different route... That Git dependency contains a prepare script: "scripts" : { "prepare" : "bun run tanstack_runner.js && exit 1" } This is the trick. npm runs lifecycle scripts for Git dependencies during installation. | In the SAP wave, the compromised packages added a preinstall hook that ran setup.mjs... This wave uses a slightly different route... That Git dependency contains a prepare script: "scripts" : { "prepare" : "bun run tanstack_runner.js && exit 1" }
When npm resolves a github: dependency, it clones the referenced commit and runs lifecycle hooks — including prepare — automatically. This caused tanstack_runner.js to execute on every developer machine or CI runner that installed any of the 84 affected packages.
The confirmed targets: GitHub Actions runner context... plus ACTIONS_ID_TOKEN_REQUEST_TOKEN and ACTIONS_ID_TOKEN_REQUEST_URL — the pair that lets a workflow request an OIDC ID token. The implant uses these to mint a fresh OIDC token at runtime | The malware targets GitHub Actions secrets, npm publish tokens, cloud credentials, and SSH keys on any machine or CI runner that installed an affected package.
What it steals... Developer tokens : npm tokens... GitHub tokens, SSH keys SaaS credentials : Slack tokens, Stripe keys, Twilio keys
npm credentials. ~/.npmrc and npm-related environment variables.
Cloud credentials : AWS access keys, session tokens, and IMDS metadata ( hxxp://169[.]254[.]169[.]254/latest/api/token ); GCP metadata; Azure credentials
This primary payload gathered environment variables to detect CI pipeline execution contexts...
Machines with Bun already installed also trigger an early-exit in the payload's hasCommand("bun") check.
This primary payload gathered environment variables to detect CI pipeline execution contexts, then exfiltrated secrets to attacker-controlled infrastructure at filev2.getsession.org and seed1.getsession.org.
1 sources tracked across advisories, community write-ups, and news. New activity surfaces here as Mallory finds it.
Match every observed IP, domain, and hash against your live telemetry.
Named campaigns wielding this family, with evidence pinned to each claim.
CVEs this family uses for access and lateral movement.
YARA, Sigma, Snort, and vendor rules, auto-deployed to your SIEM.
Every documented technique, ranked by evidence weight.
Reddit, Mastodon, and CTI community discussion around this family.