Four days ago, on October 8, 2026, version 0.5.144 of the tensorlake npm package was published. It contained the Shai-Hulud credential-stealing worm. The package has more than 100,000 lifetime installs, and the malicious release was gone from npm within about a day.
Every install of 0.5.144 that happened in that window ran the worm.
What Happened
The attacker didn't publish from a stolen npm token. On October 7 at 01:20 UTC, malicious commits were pushed to the main branch of `tensorlakeai/tensorlake` under a maintainer's name. About a day later, the project's normal GitHub Actions release workflow built and published 0.5.144. Six platform-specific `tensorlake-native-*` packages at 0.5.144 were published alongside it.
Because the release came from the real pipeline, it carried valid build provenance. Provenance tells you a package was built by the project's CI from the project's repository. It can't tell you that the repository itself was clean. Here it wasn't.
What the Payload Does
The release added a preinstall script that runs node lib/setup.mjs. npm runs preinstall before anything else, so the code executes the moment someone runs npm install. Nobody has to import the package for it to run.
-
lib/setup.mjsis a small obfuscated loader. It downloads the Bun runtime and uses it to run the second file. -
lib/Math_Symbol.jsis the payload: roughly 856 KB of obfuscated JavaScript.
The payload collects npm tokens from .npmrc, SSH keys, AWS, GCP and Azure credentials, Kubernetes and Docker configuration, HashiCorp Vault tokens, GitHub CLI config, CI tokens and .env files. It then uses any npm and GitHub credentials it finds to republish itself into other packages the victim controls. That self-republishing is what makes Shai-Hulud a worm and not a one-off compromise. Aikido also reports a dead-man's switch that wipes the machine if an embedded GitHub token is revoked.
How Hextrap Handles a Release Like This
This release had the markers Hextrap's scanner looks for in every new version of a package it already tracks:
Suspicious version diff: a new file, lib/setup.mjs, with unusually high entropy.
Obfuscated code: more than a thousand `_0x`-prefixed identifiers, the signature of javascript-obfuscator output.
Suspicious install hooks: a new `preinstall` script that runs code before anything else, plus references to `child_process`.
High-severity findings like these go to LLM review. When the review confirms a version is malicious, Hextrap flags that exact version, and firewalls block it by default with no exception list. Only the flagged release is blocked; the clean versions on either side keep installing, so a compromised release doesn't lock you out of the fix.
Detection takes time, and attackers count on that window. That's why the policy below matters even with scanning in place.
Why Hextrap Stops This
When using Hextrap Firewall or Hextrap for Agents, software packages auto-flagged as malicious are automatically blocked from being installed. Soak-time adds an extra layer of protection that's optionally enabled on each firewall.
Soak time is a firewall rule that refuses to serve any package version until it has been public for a set number of days. With a 72-hour soak time:
-
0.5.144 would not have been installable through the firewall until October 11 at 01:12 UTC.
-
By then it had long since been removed from npm.
-
Any install that resolved to 0.5.144 in the meantime would have failed with a block instead of running the worm. Projects with lockfiles pinned to 0.5.143, which is not affected, would have kept installing normally.
Soak time doesn't need anyone to have detected the attack. It only needs the ecosystem to catch a bad release faster than your waiting period, and that is the usual pattern. In our earlier analysis of 847 malicious packages, the median time to removal was 14 hours. A 72-hour window covered about 94% of them.
Why Soak Time Isn't Enough
Soak time is not a complete defense. A malicious version that stays undetected longer than your window gets through. Fortunately, because the package was auto-flagged as malicious, Hextrap still blocks the install attempt.
npm install --ignore-scripts would also have stopped this particular payload from running at install time. It's worth enabling in CI where you can, but many packages legitimately need install scripts, so it's hard to apply everywhere.
What to Do Now
- Search your lockfiles for `tensorlake` or any `tensorlake-native-*` package at `0.5.144`. Check your npm caches and CI caches too.
- If it was installed anywhere, treat that machine or runner as fully compromised. Rotate npm tokens, GitHub tokens, SSH keys and cloud credentials from a clean machine. Expect the dead-man's switch: revoking a token may trigger the wipe, so image the machine first if you need it for forensics. Then audit your npm and GitHub accounts for packages, repositories or tokens you didn't create.
- Check for the published indicators: `setup.mjs` SHA256 `25a0735d0db7dc40e5d45ce42d9c106067e6a66e184d967cfecfab17c3bcb5ef`, `Math_Symbol.js` SHA256 `b50a00900399ba99fb6ce1fc151519cb99d44320ef2a631f2237e1aea0ad6fec`, and traffic to `iseekaigogo[.]com`.
- Turn on a soak time of at least 72 hours for the registries you install from, with a short, reviewed exception list for urgent updates. In Hextrap, it's under your firewall's Security settings, alongside malicious-version blocking.
Comments