Tensorlake's malicious npm release was live for up to about 102 minutes, and carried valid provenance
The registry's own stamps give the poisoned Tensorlake release 0.5.144 up to about 102 minutes on npm: Socket flagged it after 11, and about 91 more passed before the record last changed. Valid provenance showed where it was built, not that anyone reviewed it.
By Parminder Kumar Sharma · · 22 min read

The malicious release was on npm for up to about 102 minutes, about 91 of them after Socket flagged it
The npm registry records version 0.5.144 of the tensorlake package as published at 01:12:07 UTC on 8 October 2026, which is 02:12 BST. The registry's record for the package was last changed at 02:54:27 UTC, 03:54 BST. The two stamps are 1 hour 42 minutes 20 seconds apart (derived), about 102 minutes. Version 0.5.144 carried a credential-stealing worm and is no longer in the registry. No source we read states when it was removed, so the 102 minutes is an upper bound, inferred from the last-changed stamp: the version cannot have been removed later than the last change to its record, and may have been removed earlier. Tensorlake describes itself on its homepage as "Sandboxes for AI Agents" and "Composable infrastructure for agents", and the package is its TypeScript SDK.
Socket says it flagged the release at 01:23:10 UTC, 11 minutes after publication (derived: 11 minutes 3 seconds). StepSecurity reported it to the maintainers in a public GitHub issue opened at 01:22:02 UTC, 9 minutes 55 seconds after the registry's stamp (derived). From Socket's flag to the registry's last change is 1 hour 31 minutes 17 seconds, about 91 minutes (derived). The contrast is the story: 11 minutes to flag, about 91 more minutes live. Detection was quick. What happened between the flag and the removal is not described in any source we read.
The window, 02:12 to 03:54 BST, fell in the small hours in the UK, when unattended jobs such as nightly builds and scheduled dependency updates commonly run. That is an inference about when installs happen; no source says whether any such job fetched this release.
What that does not establish.
- How many installs ran the payload. No source reports a victim count, and the public download counters cannot isolate this version.
- When the version first became downloadable, or when it was removed. The 102 minutes runs from the registry's publish stamp to the last change of its record. If the version could be fetched before its stamp, the window was longer. StepSecurity wrote that when it checked, it could still be downloaded, without saying when.
- That removal ended the exposure. A machine that installed the release in the window ran its hook at install time. Lockfiles, caches, mirrors and images keep their copies, and six native packages at the same version remain in the registry.
- How the maintainer account was taken over. Tensorlake calls it compromised and does not say how.
- That a short window means a small problem. The hook runs before anything else, and what it reads is whatever the installing process can reach.
Hours on the main branch, minutes on npm
The repository's own record puts the preparation in hours. Between 01:20:15 UTC on 7 October and 23:41:04 that day, 13 commits reached the project's main branch. GitHub's API associates none of the 13 with a pull request, which matches StepSecurity's statement for the first eight. Nine of the 13 carry GitHub's Verified status and four, all version bumps, are unsigned. The release workflow was started by hand eight times on 7 October, from 01:25:35 UTC (two runs were cancelled and six failed), and once more at 00:08:16 on 8 October, which succeeded. The build was signed at 00:16:45, and npm lists the release at 01:12:07, 23 hours 51 minutes 52 seconds after the first malicious commit (derived). The previous clean commit is stamped 21:47:59 on 6 October, and the previous clean release, 0.5.143, at 21:59:43.
A 55-minute gap does not line up. The build was signed at 00:16:45 UTC, and the workflow's own job record shows its publish step ending at 00:16:48. But npm's signed publish record is stamped 01:12:08 and the registry's stamp for the main package is 01:12:07, while the six native packages were stamped between 00:17:31 and 00:19:25. No source explains the gap for the main package. npm documents a staged mode in which a maintainer approves a staged package with two-factor authentication before it goes live. No source says whether it was used here, and this briefing does not say it was.
Valid provenance, a trusted publisher and Verified commits: each label was true
StepSecurity and Endor Labs both say the release carried build provenance, and Endor Labs calls it valid. We read the records ourselves. The npm attestation for 0.5.144 exists and the registry still serves it. We decoded its contents but did not verify its signatures, so "valid" is Endor Labs' word and the registry's, not our own test. It names the project's own release workflow, the main branch, the manual-dispatch event and the last of the 13 commits, and its transparency-log time is 00:16:45 UTC. The registry marks the publisher of the six native packages from the same run as GitHub Actions through a trusted publisher; the main package's own entry has been removed, but its attestation names the same workflow. None of that was false. All of it described where the build ran.
Labels the malicious release carried, and what each one showed. Sources: npm attestation and registry records, GitHub commit and Actions records, npm and GitHub documentation, read 8 October 2026.
- Label
- npm provenance attestation
- What it showed here
- The build ran in the project's own release workflow, from the main branch, at the last of the 13 commits
- What it does not show
- That anyone reviewed the commit. npm's own documentation says provenance does not guarantee a package has no malicious code
- Label
- Trusted publisher, GitHub Actions
- What it showed here
- The registry marked the same run's native packages as published by GitHub Actions through a trusted publisher, which npm describes as working without a long-lived npm token
- What it does not show
- Who decided to run the workflow. npm documents an option to stage a publish and require a maintainer's two-factor approval; no source says it was set
- Label
- GitHub Verified commits
- What it showed here
- Nine of the 13 show Verified. For those, GitHub itself is recorded as committer, which is how changes made in its web interface appear
- What it does not show
- Who was at the keyboard, or that anyone reviewed the change. The four unsigned bumps were not blocked, and the released commit was one of them
- Label
- A green build
- What it showed here
- The release run's type check and tests passed, then it built and published
- What it does not show
- That any test looks for an added loader. The run built what was on the branch
- Label
- An administrator's commits
- What it showed here
- Tensorlake says a repository-admin account made them
- What it does not show
- Why that account could push to main. Tensorlake says it has removed the administrator bypass from its branch rules
| Label | What it showed here | What it does not show |
|---|---|---|
| npm provenance attestation | The build ran in the project's own release workflow, from the main branch, at the last of the 13 commits | That anyone reviewed the commit. npm's own documentation says provenance does not guarantee a package has no malicious code |
| Trusted publisher, GitHub Actions | The registry marked the same run's native packages as published by GitHub Actions through a trusted publisher, which npm describes as working without a long-lived npm token | Who decided to run the workflow. npm documents an option to stage a publish and require a maintainer's two-factor approval; no source says it was set |
| GitHub Verified commits | Nine of the 13 show Verified. For those, GitHub itself is recorded as committer, which is how changes made in its web interface appear | Who was at the keyboard, or that anyone reviewed the change. The four unsigned bumps were not blocked, and the released commit was one of them |
| A green build | The release run's type check and tests passed, then it built and published | That any test looks for an added loader. The run built what was on the branch |
| An administrator's commits | Tensorlake says a repository-admin account made them | Why that account could push to main. Tensorlake says it has removed the administrator bypass from its branch rules |
The friendly-name fallacy. A label records where a change came from. A control stops a change that should not happen. Here the labels were true and nothing was stopped. Tensorlake's own list of what it changed afterwards is a list of controls: no administrator bypass of the branch rules, required signatures, no direct pushes to main, a second reviewer on the environment that publishes with self-review blocked, install scripts off in CI, and a check that fails the build if a published manifest declares any install-time script. The NCSC's guidance on the build and deployment pipeline gives, as its example of bad practice, a team that follows a peer review process but has no technical control preventing direct changes to its main branch. We do not know what review process Tensorlake followed. We do know direct changes to main were possible, because thirteen of them were made.
An earlier briefing shows the same trust one level up: Disabling a repository is not removing the malware, and on 16 September the tags started working again.
What the worm does, at defender level, and who says so
The behaviour below comes from static analysis by Socket, StepSecurity, Endor Labs, OX Security and Aikido. StepSecurity says it decoded the payload without running it. Method, not accusation. All five sell software supply chain security products, and four of the five posts include a section on how their product helps; Microsoft, cited below, sells endpoint security. That is a reason to know whose analysis this is, not to doubt it: the vendors agree on most of what follows. This briefing prints no commands, file names, hashes, domains or account names. Detection teams should take indicators from the vendors' own posts.
Stated and not stated about the payload. Sources: Socket, StepSecurity, Endor Labs, OX Security and Aikido posts of 8 October 2026, as read.
- Topic
- Trigger
- Stated by the vendors
- An install-time hook, called preinstall, runs an obfuscated loader that fetches a JavaScript runtime and runs a payload of about 856 KB. The SDK need not be imported or started
- Not stated
- How many installs ran it
- Topic
- Targets
- Stated by the vendors
- npm and GitHub tokens; cloud credentials, Vault and Kubernetes; SSH keys; environment files; wallets; messaging data; AI coding tool configuration. A browser-data tool is also fetched
- Not stated
- Which credentials, if any, were taken from a real machine
- Topic
- Exfiltration
- Stated by the vendors
- Encrypted, to a public GitHub repository with a distinctive description, or to a remote server (StepSecurity). The server address is looked up through a blockchain contract (Socket, Aikido)
- Not stated
- Where stolen data went in any confirmed case
- Topic
- Spread
- Stated by the vendors
- A stolen npm token republishes the victim's packages, with provenance (Socket). A stolen GitHub token commits AI tool and editor configuration files under a fake author (StepSecurity)
- Not stated
- That any downstream package was published; none is reported in the sources we read. Aikido saw no sign of publication to PyPI or Cargo
- Topic
- Revocation trap
- Stated by the vendors
- A monitor checks the stolen GitHub token every 60 seconds for up to 24 hours. If the token is revoked it is reported to delete the home directory (StepSecurity, OX, Aikido)
- Not stated
- A demonstrated wipe. This is a reading of the code, and no source reports one happening
| Topic | Stated by the vendors | Not stated |
|---|---|---|
| Trigger | An install-time hook, called preinstall, runs an obfuscated loader that fetches a JavaScript runtime and runs a payload of about 856 KB. The SDK need not be imported or started | How many installs ran it |
| Targets | npm and GitHub tokens; cloud credentials, Vault and Kubernetes; SSH keys; environment files; wallets; messaging data; AI coding tool configuration. A browser-data tool is also fetched | Which credentials, if any, were taken from a real machine |
| Exfiltration | Encrypted, to a public GitHub repository with a distinctive description, or to a remote server (StepSecurity). The server address is looked up through a blockchain contract (Socket, Aikido) | Where stolen data went in any confirmed case |
| Spread | A stolen npm token republishes the victim's packages, with provenance (Socket). A stolen GitHub token commits AI tool and editor configuration files under a fake author (StepSecurity) | That any downstream package was published; none is reported in the sources we read. Aikido saw no sign of publication to PyPI or Cargo |
| Revocation trap | A monitor checks the stolen GitHub token every 60 seconds for up to 24 hours. If the token is revoked it is reported to delete the home directory (StepSecurity, OX, Aikido) | A demonstrated wipe. This is a reading of the code, and no source reports one happening |
The worm is a family, not a one-off. Microsoft Threat Intelligence described an August wave of more than 400 packages and said the evidence pointed to stolen maintainer credentials, and Socket says the hook and payload names at Tensorlake match it. The TanStack postmortem of 11 May describes 42 packages and 84 versions, detected publicly within 20 to 26 minutes, by a different route and with no npm tokens stolen. CISA's alert of 23 September 2025 put the first wave at over 500 packages. An earlier briefing, PhantomSub follows channels, not groups, shows the other half of the problem: registries and malware records do not always agree on what is still being served.
What Tensorlake has said, and what it has not
The only statement from the company that we found is the text of a pull request, number 1016, merged at 04:32:11 UTC, 3 hours 20 minutes after the listing (derived). We found no post on Tensorlake's blog, whose newest entry was dated 16 September when we read it, and no notice on its status page, which does not display without a script. Treat the pull request as a primary but partial statement, written by engineers for engineers.
Tensorlake's pull request 1016, stated and not stated. Source: the pull request text, read 8 October 2026.
- Topic
- What happened
- Stated
- The payload was committed straight to main by a repository-admin account through GitHub's web interface, then released by manually dispatching the release workflow. npm has removed the version
- Not stated
- How the account was compromised, and when the maintainers first saw the problem
- Topic
- Changes made
- Stated
- Administrator bypass removed from the branch rules; signatures required; no direct pushes; a second reviewer for publishing, with self-review blocked; install scripts off in CI; a tripwire against install-time scripts; version bumped to 0.5.145
- Not stated
- What the branch rules and the publishing environment looked like before
- Topic
- Still to do at merge time
- Stated
- Lock the compromised account and revoke its sessions and keys; unpublish the six native 0.5.144 packages; rotate the secrets available to the release workflow
- Not stated
- Whether each is done. The six native packages were still in the registry when we last looked
- Topic
- Users
- Stated
- Nothing
- Not stated
- Any notice to users, or which credentials the release workflow could reach
| Topic | Stated | Not stated |
|---|---|---|
| What happened | The payload was committed straight to main by a repository-admin account through GitHub's web interface, then released by manually dispatching the release workflow. npm has removed the version | How the account was compromised, and when the maintainers first saw the problem |
| Changes made | Administrator bypass removed from the branch rules; signatures required; no direct pushes; a second reviewer for publishing, with self-review blocked; install scripts off in CI; a tripwire against install-time scripts; version bumped to 0.5.145 | What the branch rules and the publishing environment looked like before |
| Still to do at merge time | Lock the compromised account and revoke its sessions and keys; unpublish the six native 0.5.144 packages; rotate the secrets available to the release workflow | Whether each is done. The six native packages were still in the registry when we last looked |
| Users | Nothing | Any notice to users, or which credentials the release workflow could reach |
Where the sources disagree, and how this briefing treats each
Disagreements between the sources and the records. Sources as named in each row, read 8 October 2026; the GitHub advisory and OSV records are listed in the sources.
- Question
- Which commit introduced the payload
- What the sources say
- Aikido and a comment on the maintainers' issue name the seventh commit. StepSecurity, Endor Labs and Tensorlake's pull request start at the first
- How we treat it
- The commit record: the first added both payload files at 01:20:15 and later commits changed them. We count from the first: 23 h 51 m 52 s to the listing, against Aikido's 'about 20 hours' (21 h 27 m from its commit, derived)
- Question
- Does the loader run in CI
- What the sources say
- StepSecurity says it skips CI. Socket and Endor Labs treat CI as a target
- How we treat it
- Unresolved. Treat CI secrets as exposed
- Question
- Which versions are affected
- What the sources say
- Vendors: 0.5.144. GitHub's advisory, updated at 04:15 UTC, and the OSV record list that version and also a range from zero with no fixed version. Endor Labs says 0.5.143 and earlier are clean
- How we treat it
- A scanner that reads the range can flag clean versions. Check the version, not the range
- Question
- Is the release still downloadable
- What the sources say
- StepSecurity wrote that when it checked, it was. Endor Labs and The Hacker News say it is removed
- How we treat it
- Consistent with a check before removal. The registry's lookup for the version returned not found when we read it
- Question
- How popular is the package
- What the sources say
- Socket and Endor Labs: about 12,000 downloads a week. The npm API: 18,826 for 28 September to 4 October. Aikido: over 100,000 lifetime
- How we treat it
- Different windows. None counts 0.5.144
- Question
- What order to rotate in
- What the sources say
- Socket, StepSecurity and OX: remove the persistence monitor before revoking any token. GitHub's advisory text and the NCSC's June blog: rotate at once
- How we treat it
- The sources differ. Follow your incident-response lead; see the checklist
- Question
- The cause and the actor
- What the sources say
- Endor Labs: most likely a compromised maintainer account, as inference. Tensorlake calls the account compromised. OX: new encryption keys may mean an independent actor. Microsoft's August finding was stolen maintainer credentials
- How we treat it
- No source says how, or who. Do not read the August finding across
| Question | What the sources say | How we treat it |
|---|---|---|
| Which commit introduced the payload | Aikido and a comment on the maintainers' issue name the seventh commit. StepSecurity, Endor Labs and Tensorlake's pull request start at the first | The commit record: the first added both payload files at 01:20:15 and later commits changed them. We count from the first: 23 h 51 m 52 s to the listing, against Aikido's 'about 20 hours' (21 h 27 m from its commit, derived) |
| Does the loader run in CI | StepSecurity says it skips CI. Socket and Endor Labs treat CI as a target | Unresolved. Treat CI secrets as exposed |
| Which versions are affected | Vendors: 0.5.144. GitHub's advisory, updated at 04:15 UTC, and the OSV record list that version and also a range from zero with no fixed version. Endor Labs says 0.5.143 and earlier are clean | A scanner that reads the range can flag clean versions. Check the version, not the range |
| Is the release still downloadable | StepSecurity wrote that when it checked, it was. Endor Labs and The Hacker News say it is removed | Consistent with a check before removal. The registry's lookup for the version returned not found when we read it |
| How popular is the package | Socket and Endor Labs: about 12,000 downloads a week. The npm API: 18,826 for 28 September to 4 October. Aikido: over 100,000 lifetime | Different windows. None counts 0.5.144 |
| What order to rotate in | Socket, StepSecurity and OX: remove the persistence monitor before revoking any token. GitHub's advisory text and the NCSC's June blog: rotate at once | The sources differ. Follow your incident-response lead; see the checklist |
| The cause and the actor | Endor Labs: most likely a compromised maintainer account, as inference. Tensorlake calls the account compromised. OX: new encryption keys may mean an independent actor. Microsoft's August finding was stolen maintainer credentials | No source says how, or who. Do not read the August finding across |
What the registries and databases hold now
Read at 10:50 UTC on 8 October and again at 11:05 UTC (12:05 BST), with no change:
- The main package. Version 0.5.144 is not in the registry, and a lookup of the version returns not found. The latest tag is 0.5.143. There is no 0.5.145 of the main package, although Tensorlake's pull request bumped the version to it.
- The six native packages. All six still carry 0.5.144. They contain no install-time script, and Endor Labs found no payload in them, but it says to treat them as part of the affected release and avoid them. Clean 0.5.145 versions of the six were stamped between 05:22:05 and 05:25:17 UTC.
- Other registries. PyPI and crates.io both show 0.5.143 as the newest version. Aikido saw no sign of publication there either.
- Advisory records. GitHub published a malware advisory with no CVE at 02:54:39 UTC, 12 seconds after the registry's last change (derived). OSV carries it as MAL-2026-17650. A keyword search of the National Vulnerability Database for the package name returned no records at 10:50 UTC.
- CISA's catalogue. Version 2026.10.04, released 4 October with 1,734 entries, has no Tensorlake entry and predates the release. The May TanStack wave did get a CVE and was added to the catalogue on 27 May, so a package worm can reach the catalogue. As of these reads, this one has neither a CVE nor an entry.
How many were affected: no source says
No source we read reports a victim count, a number of installs of 0.5.144, or which credentials were taken from any real machine. The figures in circulation measure other things.
Figures in circulation and what they do and do not measure. Sources: Socket, Endor Labs, Aikido, the npm downloads API, GitHub's repository API and search, read 8 October 2026.
- Figure
- About 12,000 downloads a week (Socket, Endor Labs)
- What it measures
- The package's overall usage
- What it does not measure
- Downloads of 0.5.144 or infections. Socket says so itself
- Figure
- 18,826 downloads from 28 September to 4 October (npm API); 2,689 a day on average (derived)
- What it measures
- Seven days of downloads of all versions
- What it does not measure
- Anything after 5 October. The daily series reads 0 for 6 to 8 October, what looks like counter lag, not an absence of installs (inference)
- Figure
- Over 100,000 lifetime installs (Aikido)
- What it measures
- A cumulative count, as reported
- What it does not measure
- Recent installs, or installs of the malicious version
- Figure
- 1,019 stars on GitHub
- What it measures
- Interest in the repository
- What it does not measure
- Use of the package
- Figure
- 42 public repositories created since 7 October with the worm's description (GitHub search, 11:05 UTC; 35 at about 10:30 UTC)
- What it measures
- Repositories carrying a description the worm is reported to use
- What it does not measure
- Tensorlake victims. Earlier waves used the same description: one count had 546 such repositories on 4 August. The earliest of the 42 was created at 03:03:00 UTC on 8 October, 8 minutes 33 seconds after the registry's last change. OX counted five when it wrote
| Figure | What it measures | What it does not measure |
|---|---|---|
| About 12,000 downloads a week (Socket, Endor Labs) | The package's overall usage | Downloads of 0.5.144 or infections. Socket says so itself |
| 18,826 downloads from 28 September to 4 October (npm API); 2,689 a day on average (derived) | Seven days of downloads of all versions | Anything after 5 October. The daily series reads 0 for 6 to 8 October, what looks like counter lag, not an absence of installs (inference) |
| Over 100,000 lifetime installs (Aikido) | A cumulative count, as reported | Recent installs, or installs of the malicious version |
| 1,019 stars on GitHub | Interest in the repository | Use of the package |
| 42 public repositories created since 7 October with the worm's description (GitHub search, 11:05 UTC; 35 at about 10:30 UTC) | Repositories carrying a description the worm is reported to use | Tensorlake victims. Earlier waves used the same description: one count had 546 such repositories on 4 August. The earliest of the 42 was created at 03:03:00 UTC on 8 October, 8 minutes 33 seconds after the registry's last change. OX counted five when it wrote |
Download counters do not isolate a version here. The npm per-version endpoint for the last week has no entry for 0.5.141 to 0.5.144, which were published on 6 and 8 October, and puts 12,728 of its 18,204 counted downloads, 69.9% (derived), on one old version. A story from the day before shows why a download count is a poor measure of harm: The Hacker News reported eight npm packages "downloaded 40,767 times", a cumulative figure over years for packages that were malicious by design, a different campaign with a different meaning.
What UK readers can lean on, and what Cyber Essentials does not say
The NCSC's blog Software supply chain attacks: check your dependencies, published on 4 June 2026, names the May Mini Shai-Hulud wave. It says damage then was limited by the speed of discovery and that later similar attacks went undetected for longer and spread more widely. Its advice includes avoiding automatic adoption of new dependency versions without review, deploying through controlled pipelines rather than developer devices, keeping sensitive credentials off developer workstations and pausing automatic updates where compromise may be present. It also says to rotate credentials immediately if compromise is suspected, which is one side of the ordering dispute above.
The Software Security Code of Practice asks suppliers to assess risks from third-party components (principle 1.2), protect the build environment against unauthorised access (2.1), control and log changes to it (2.2) and tell customers about notable incidents (4.3). It says open-source maintainers are not its primary audience, and that risks in open-source code are for end users, or proprietary developers who use it, to manage. A UK organisation that installs a package like this one is the party the Code leaves holding the risk.
What Cyber Essentials v3.3 (April 2026) says, and does not say, that bears on this incident. Source: the requirements for IT infrastructure document, read in full.
- Topic
- Supply chain and packages
- What the requirements say
- Software is defined to include extensions, interpreters, scripts and libraries
- What they do not say
- The words supply chain, package, npm and open source do not appear. Dependencies appears once, about overlaps between requirements
- Topic
- Updates
- What the requirements say
- In-scope software must be updated within 14 days of release where the update fixes vulnerabilities rated critical or high, CVSS 7 or above, or not rated
- What they do not say
- How old a release should be before you adopt it. A delay of a few days sits inside the 14 days (inference), but the rule concerns vulnerability fixes
- Topic
- Build and release
- What the requirements say
- A scope note: bespoke and custom components of web applications are out of scope; it points to the Software Security Code of Practice
- What they do not say
- Branch protection, peer review, secrets, repositories, CI/CD and build pipelines are not mentioned
- Topic
- Malware protection
- What the requirements say
- Anti-malware, or application allow-listing restricted by code signing
- What they do not say
- Install-time scripts in dependencies
| Topic | What the requirements say | What they do not say |
|---|---|---|
| Supply chain and packages | Software is defined to include extensions, interpreters, scripts and libraries | The words supply chain, package, npm and open source do not appear. Dependencies appears once, about overlaps between requirements |
| Updates | In-scope software must be updated within 14 days of release where the update fixes vulnerabilities rated critical or high, CVSS 7 or above, or not rated | How old a release should be before you adopt it. A delay of a few days sits inside the 14 days (inference), but the rule concerns vulnerability fixes |
| Build and release | A scope note: bespoke and custom components of web applications are out of scope; it points to the Software Security Code of Practice | Branch protection, peer review, secrets, repositories, CI/CD and build pipelines are not mentioned |
| Malware protection | Anti-malware, or application allow-listing restricted by code signing | Install-time scripts in dependencies |
Cyber Essentials certification therefore says nothing about whether a developer machine or build runner installs a package within the hour of its release. These are controls a UK team can apply itself, with the catch for each. Sources: npm's configuration, trusted publishing and staged publishing documentation, the GitHub changelog for npm 12, GitHub's Dependabot and environments documentation, the NCSC pages above and Tensorlake's pull request.
Controls a UK team can apply, what each would have done here, and the catch.
- Control
- A minimum release age for new versions
- What it would have done here
- The release lived for about 102 minutes, so a delay of a day or more keeps it out of any install that obeys the setting. npm has a setting in days; Dependabot waits 3 days by default for version updates, not security updates
- The catch
- It works only if someone flags the release within the delay, and it holds back real fixes with a warning unless the package is excluded
- Control
- Install scripts off in CI
- What it would have done here
- The payload needed an install-time hook. npm 12, generally available on 8 July 2026 (92 days before 8 October, derived), runs dependency install scripts only if allowed, and older npm can be told the same. Tensorlake has turned them off in its CI
- The catch
- It covers install time, not code that runs when a package is imported. A laptop on an older npm with scripts allowed is untouched
- Control
- Trusted publishing with a second approver
- What it would have done here
- Tensorlake now requires a second reviewer on its publishing environment, self-review blocked, and no administrator bypass on main. npm documents trusted publishing limited to staging, so a maintainer's two-factor approval is needed before release
- The catch
- A second approver helps only if they look at what changed; GitHub needs just one of the listed reviewers. Approving a publish is not reviewing the code
- Control
- Short-lived tokens
- What it would have done here
- The worm republishes with a stolen npm token. npm documents token expiry dates, and trusted publishing removes long-lived write tokens from the build
- The catch
- A token works inside its lifetime, and trusted publishing authenticates the workflow, which is what was used here
- Control
- Secrets off developer machines
- What it would have done here
- The NCSC says to keep sensitive credentials off developer workstations. The worm reads what the installing process can read
- The catch
- Developers still need some access. Scoped, short-lived credentials are the middle path
| Control | What it would have done here | The catch |
|---|---|---|
| A minimum release age for new versions | The release lived for about 102 minutes, so a delay of a day or more keeps it out of any install that obeys the setting. npm has a setting in days; Dependabot waits 3 days by default for version updates, not security updates | It works only if someone flags the release within the delay, and it holds back real fixes with a warning unless the package is excluded |
| Install scripts off in CI | The payload needed an install-time hook. npm 12, generally available on 8 July 2026 (92 days before 8 October, derived), runs dependency install scripts only if allowed, and older npm can be told the same. Tensorlake has turned them off in its CI | It covers install time, not code that runs when a package is imported. A laptop on an older npm with scripts allowed is untouched |
| Trusted publishing with a second approver | Tensorlake now requires a second reviewer on its publishing environment, self-review blocked, and no administrator bypass on main. npm documents trusted publishing limited to staging, so a maintainer's two-factor approval is needed before release | A second approver helps only if they look at what changed; GitHub needs just one of the listed reviewers. Approving a publish is not reviewing the code |
| Short-lived tokens | The worm republishes with a stolen npm token. npm documents token expiry dates, and trusted publishing removes long-lived write tokens from the build | A token works inside its lifetime, and trusted publishing authenticates the workflow, which is what was used here |
| Secrets off developer machines | The NCSC says to keep sensitive credentials off developer workstations. The worm reads what the installing process can read | Developers still need some access. Scoped, short-lived credentials are the middle path |
What to do, in the order worth doing it
Take this with you
Defender checklist
- Find out whether the affected version was ever installed. Search lockfiles in every repository and branch, CI logs and caches, artifact proxies and mirrors, container images and developer machines for 0.5.144 of the main package and of the six native packages, including as a transitive dependency. The registry's stamps put the exposure at 01:12 to 02:54 UTC on 8 October (02:12 to 03:54 BST), but a cached or mirrored copy can be installed later.
- If you find it, treat the machine or runner as compromised: isolate it from the network, keep it, and call your incident-response lead before rotating anything.
- Settle the order of rotation with that lead, using the warning above, and back up what you cannot lose first.
- Treat CI secrets as exposed wherever the version ran. StepSecurity says the loader skips CI and Socket and Endor Labs treat CI as a target; rotating costs less than guessing.
- Rotate what the process could read: npm and GitHub tokens, cloud keys, SSH keys, Kubernetes and Vault credentials, environment-file secrets, AI tool keys and browser-saved passwords. Rebuild any machine you cannot vouch for.
- Check for spread: unexpected new public repositories in your GitHub accounts, new workflows, new published versions of your own packages, commits by an unrecognised author with a generic dependency-update message, and AI assistant or editor configuration files nobody on the team added.
- Pin to 0.5.143, the latest tag of the main package, until a clean main release appears, and avoid all six native 0.5.144 packages.
- Then fix the habit: a minimum release age, install scripts off in CI, lockfile-only installs in CI, and no install of a version less than a day or two old without a look.
- If you publish packages: no direct pushes or administrator bypass on the release branch, required signatures, a second approver on the publishing environment with self-review blocked, staged releases that need a maintainer's two-factor approval, and short-lived tokens.
- Re-read the GitHub advisory and the registry before closing the ticket. Records move: the repository count in this briefing rose from 35 to 42 in about 20 minutes.
What is not established, and what we could not read
- Any victim count, which credentials were taken from a real machine, or whether the worm published any downstream package.
- When 0.5.144 first became fetchable, and whether the latest tag ever pointed at it. The registry record keeps no tag history.
- How the maintainer account was compromised, and whether the same access reached anything else.
- Why the main package was recorded 55 minutes after its build was signed.
- Who is behind it, and whether the revocation trap works as the vendors read it. No source reports a wipe.
- Aikido's post on X, which needs a login (its blog post was read), and Tensorlake's status page, which needs a script.
The question
The labels on this release were valid. The build was signed, the publisher was trusted and nine of the thirteen commits were Verified. The release was on npm in the small hours for up to about 102 minutes, and about 91 of them came after a security company had flagged it. What would have stopped it sits on Tensorlake's own fix list and on your side of the install: a delay before new versions are trusted, scripts that do not run, and a second person before release.
So if a package your build depends on were poisoned at 02:12 tonight, which of your machines would install it before anyone is awake, and what could it read when it did?
Key facts
Sources
- PrimaryThe registry record for the tensorlake package, read at 10:20 and again at 10:42 and at the end of the build (11:05 UTC (12:05 BST)): the publish stamp 01:12:07 UTC for 0.5.144, the last-changed stamp 02:54:27 UTC, the latest tag 0.5.143 and the absence of 0.5.145. The primary source for the window.npm registryaccessed 2026-10-08
- PrimaryThe registry records for the six tensorlake-native packages (this URL is one of the six), read at 10:50 UTC: 0.5.144 stamped 00:17:31 to 00:19:25 UTC with no install-time script, still present, and the clean 0.5.145 stamped 05:22 to 05:25 UTC.npm registryaccessed 2026-10-08
- PrimaryGitHub malware advisory GHSA-rqxj-g25x-4v9v, published 02:54:39 UTC on 8 October 2026 with no CVE, updated at 04:15 UTC to add a range from zero with no fixed version. Read through GitHub's advisory API at 10:42 UTC.GitHubaccessed 2026-10-08
- PrimaryOpen Source Vulnerabilities record MAL-2026-17650, an alias of the GitHub advisory, listing 0.5.144 and a range from zero with no fixed version, read at 10:42 UTC.OSVaccessed 2026-10-08
- PrimaryThe public GitHub issue StepSecurity opened with the maintainers at 01:22:02 UTC on 8 October 2026 and one later comment, read through the GitHub API.GitHubaccessed 2026-10-08
- PrimaryTensorlake's pull request 1016, merged at 04:32:11 UTC on 8 October 2026: the only statement from the company that was found, read in full through the GitHub API. It describes the commits, the manual release, the changes made and the work still to do.GitHubaccessed 2026-10-08
- PrimaryGitHub's commit records for the main branch since 6 October 21:00 UTC, with each commit's verification status and committer, the comparison with the last clean commit and the per-commit pull request lookups, read between 10:20 and 10:55 UTC. Source of the 13 commits, the nine Verified and the four unsigned.GitHubaccessed 2026-10-08
- PrimaryGitHub's Actions records for the release workflow: eight manual runs on 7 October (two cancelled, six failed), the successful run from 00:08:16 UTC on 8 October with its job and step times, read through the GitHub API.GitHubaccessed 2026-10-08
- PrimaryThe npm attestation bundle for 0.5.144, still served after the removal and identical on a second read: the provenance statement (transparency-log time 00:16:45 UTC, workflow, branch, event and commit) and npm's own publish record (01:12:08 UTC).npm registryaccessed 2026-10-08
- PrimaryGitHub repository search for the worm's reported description, created since 7 October: 35 at about 10:30 UTC, 42 at 11:05 UTC, earliest created 03:03:00 UTC. Counts only; no owners or names were recorded.GitHubaccessed 2026-10-08
- PrimaryTensorlake's homepage, read on 8 October 2026: the product description used in the opening.Tensorlakeaccessed 2026-10-08
- PrimaryTensorlake's blog, read at 10:57 UTC on 8 October 2026: no post about the incident, the newest entry dated 16 September.Tensorlakeaccessed 2026-10-08
- PrimarySocket's analysis, 8 October 2026: the publish time 01:12:07 UTC, its flag at 01:23:10 UTC, the install-time hook, the targets, the spread, the revocation trap and the remediation order. Socket sells software supply chain security products.Socketaccessed 2026-10-08
- PrimaryStepSecurity's analysis, 8 October 2026: the first malicious commit at 01:20 UTC on 7 October, no pull requests, the revocation trap, the CI skip and the remediation order. StepSecurity sells software supply chain security products.StepSecurityaccessed 2026-10-08
- PrimaryEndor Labs' analysis, 8 October 2026: the six native packages with no payload found, 0.5.143 clean, the CI check, the weekly downloads and the compromised-account inference. Endor Labs sells software supply chain security products.Endor Labsaccessed 2026-10-08
- PrimaryOX Security's analysis, 8 October 2026: the remediation order, the new encryption keys and the count of five repositories. OX sells software supply chain security products.OX Securityaccessed 2026-10-08
- PrimaryAikido's analysis, 8 October 2026: the later commit it names, the about 20 hours, over 100,000 lifetime installs and no sign of publication to PyPI or Cargo. Aikido sells software supply chain security products.Aikido Securityaccessed 2026-10-08
- PrimaryMicrosoft's analysis of the August 2026 wave of the same worm family, 4 August 2026: more than 400 packages and the stolen maintainer credentials finding. Microsoft sells endpoint security products.Microsoft Threat Intelligenceaccessed 2026-10-08
- PrimaryTanStack's postmortem of the 11 May 2026 compromise: 42 packages, 84 versions, detected within 20 to 26 minutes, no npm tokens stolen.TanStackaccessed 2026-10-08
- PrimaryCISA alert of 23 September 2025 on the first Shai-Hulud wave: over 500 packages and the lockfile and cache search advice.CISAaccessed 2026-10-08
- PrimaryThe npm downloads API for the package: the daily series, 18,826 for 28 September to 4 October, zero for 6 to 8 October, and the per-version endpoint for the last week.npmaccessed 2026-10-08
- PrimaryKnown Exploited Vulnerabilities catalogue, version 2026.10.04 released 4 October 2026, 1,734 entries, read at 10:42 UTC and again at the end of the build (11:05 UTC (12:05 BST)): no Tensorlake entry; the TanStack entry added 27 May 2026.CISAaccessed 2026-10-08
- PrimaryNVD keyword search for tensorlake, run at 10:50 UTC on 8 October 2026: no records.NIST NVDaccessed 2026-10-08
- PrimaryPyPI record for the Python package: newest version 0.5.143, read at 10:50 UTC.PyPIaccessed 2026-10-08
- Primarycrates.io record for the Rust crate: newest version 0.5.143, read at 10:50 UTC.crates.ioaccessed 2026-10-08
- Primarynpm documentation on provenance: it does not guarantee a package has no malicious code.npm Docsaccessed 2026-10-08
- Primarynpm documentation on trusted publishing: the publisher is a workflow, the optional environment and the allowed actions.npm Docsaccessed 2026-10-08
- Primarynpm documentation on staged publishing: a maintainer approves a staged package with two-factor authentication before it goes live.npm Docsaccessed 2026-10-08
- Primarynpm version 12 configuration documentation: the minimum release age setting in days and the setting that turns install scripts off.npm Docsaccessed 2026-10-08
- PrimaryGitHub changelog of 8 July 2026: npm 12 is generally available and dependency install scripts, git and remote dependencies are opt-in by default.GitHub Changelogaccessed 2026-10-08
- PrimaryDependabot options reference: a default cooldown of 3 days for version updates, not security updates.GitHub Docsaccessed 2026-10-08
- PrimaryGitHub documentation on environments: required reviewers, one of whom need approve, and the option to prevent self-review.GitHub Docsaccessed 2026-10-08
- PrimarySoftware supply chain attacks: check your dependencies, a blog post published 4 June 2026, read in full: the advice on new versions, pipelines, workstation credentials and rotation.NCSCaccessed 2026-10-08
- PrimarySecure development and deployment guidance, secure the build and deployment pipeline, first published 2019: technical controls so peer review cannot be bypassed, avoiding self policing and hard breaks.NCSCaccessed 2026-10-08
- PrimarySoftware Security Code of Practice: principles 1.2, 2.1, 2.2 and 4.3 and the statement on open-source maintainers.GOV.UKaccessed 2026-10-08
- PrimaryCyber Essentials: Requirements for IT Infrastructure v3.3, April 2026, read in full: the definition of software, the 14 days, the software development scope note, and the absence of supply chain, branch, secret and pipeline terms.NCSCaccessed 2026-10-08
- Reported byThe Hacker News on the Tensorlake compromise, 8 October 2026: a news pointer to the vendor posts.The Hacker Newsaccessed 2026-10-08
- Reported byThe Hacker News, 7 October 2026: eight malicious npm packages downloaded 40,767 times, used only as a contrast for what a download count measures.The Hacker Newsaccessed 2026-10-08
- Reported byThe Hacker News on the August wave: 546 repositories with the same description on 4 August, used only to show the description recurs.The Hacker Newsaccessed 2026-10-08


