Tech Digest Deep Dive - Oct 14, 2026

npm Supply Chain Attacks in 2026: Shai-Hulud Worms, Hostage Tokens, and Why Provenance Is Not Enough

Key facts

In the first eight days of October 2026, attackers poisoned the official Tensorlake npm SDK, planted fake security-audit workflows across hundreds of GitHub repositories, and pushed malicious commits straight to a maintainer's main branch.

In the first eight days of October 2026, attackers poisoned the official Tensorlake npm SDK, planted fake security-audit workflows across hundreds of GitHub repositories, and pushed malicious commits straight to a maintainer's main branch. None of these attacks used a typosquat or a brand-new package. Each shipped from a trusted account or the project's own release pipeline, and one carried a valid npm provenance attestation that a standard supply chain control would have accepted. That is the defining shift of 2026: malicious code no longer needs to impersonate a library, because it can become the next version of one. StepSecurity tracked 56 distinct malicious-package incidents in the twelve months to August 2026, roughly one confirmed supply chain attack every three days since March.

What happened in the first week of October 2026

October opened with a run of separate compromises, not one event. On October 7 and 8, the GhostAction campaign resurged with a more capable payload pushed through stolen maintainer accounts, reaching tens of thousands of repositories in about two days. On October 8 at 01:12 UTC, the Tensorlake repository's own release workflow published tensorlake@0.5.144 to npm, a release that StepSecurity describes as a worm with a hostage token attached.

The week reflects an attack rate, not luck: through February 2026 a confirmed supply chain compromise came roughly once a month, then March 2026 hit 13 incidents in a single month and the rate never came back down. StepSecurity's annual report counts 6 incidents from August 2025 to January 2026, then 50 in the six and a half months that followed, an increase of more than 8x.

The Tensorlake worm and the hostage token trap

Tensorlake is a serverless sandbox for AI agents, and its TypeScript SDK has a reported lifetime install count above 100,000. The malicious release did not arrive through a stolen token or a hijacked registry session. The first rogue commit landed directly on main at 01:20 UTC on October 7 under a maintainer's name, followed by seven more commits that added a preinstall line to package.json. None of them went through a pull request. About 24 hours later the repository's own release workflow built and published 0.5.144, which is why npm shows a provenance attestation for pure malware.

Installation is the detonation. The preinstall hook runs setup.mjs, which skips itself on CI so developer machines are the target, downloads the Bun runtime, and executes an 856 KB obfuscated payload. That payload harvests GitHub and npm tokens, cloud access keys, Kubernetes and Vault secrets, SSH private keys, and credentials and configuration files for browser and AI coding tools. It exfiltrates to a public GitHub repository it creates in the victim's own account, described as "Shai-Hulud: Here We Go Again," or to the domain iseekaigogo.com. With a stolen npm token it republishes the victim's packages with itself injected. With a stolen GitHub token it commits .claude/settings.json and .vscode/tasks.json backdoors authored as claude@users.noreply.github.com under the message "chore: update dependencies."

The trap is the part teams will remember. When the malware obtains a GitHub token, it installs a persistence service called gh-token-monitor that checks the token against the GitHub API every 60 seconds for up to 24 hours. If GitHub rejects it, meaning someone revoked it, the service runs rm -rf ~/ on Linux and macOS, or a PowerShell deletion of the user profile on Windows. Revoking a credential is normally step one of incident response. Here it is the trigger.

The Tensorlake guidance is therefore explicit: do not revoke any GitHub token until the monitor is removed. Find ~/.config/gh-token-monitor/, check the token file inside to see which credential it holds, disable and delete the service, and only then rotate GitHub and npm tokens, cloud keys, SSH keys, Kubernetes and Vault credentials, .env secrets, and browser passwords. Pinning the package to 0.5.143 and adding ignore-scripts=true to .npmrc stops this class of install hook outright. The ordering problem generalizes: a payload that reacts to rotation adds a step to every runbook, and teams that skip it risk data destruction on top of data theft.

Provenance attestations prove where a package was built, not that it is safe

TanStack pushed the same idea to its logical conclusion five months earlier. On May 11, 2026, between 19:20 and 19:26 UTC, 84 malicious versions were published across 42 packages in the @tanstack/ namespace, including the router and Start families. Per TanStack's postmortem, the attacker chained three weaknesses that individually would not have been enough: a pull_request_target "Pwn Request" misconfiguration, GitHub Actions cache poisoning across the fork-to-base trust boundary, and extraction of an OIDC token from the runner process memory at runtime. The publish was authenticated through TanStack's legitimate OIDC trusted-publisher binding, no npm tokens were stolen, and the release workflow itself was never modified. The real pipeline published the malware, after being hijacked mid-run.

Tracked as CVE-2026-45321, the incident is also, per Snyk, the first documented case of a malicious npm package carrying valid SLSA Build Level 3 provenance attestations. Sigstore verified the build correctly, because the build really was the project's build. Provenance answers where an artifact came from. It does not answer whether you should run it, and that distinction is now the most important thing to understand about software supply chain controls.

The blast radius shows why. The payload was a roughly 2.3 MB obfuscated router_init.js delivered through a malicious optionalDependencies entry pointing at an orphan commit in the fork network, and it executed during the normal npm install lifecycle. It harvested AWS, GCP, Kubernetes, Vault, npm, GitHub, and SSH credentials, then exfiltrated them over the Session messenger file-upload network instead of an attacker-controlled server, which defeats IP and domain blocking. It self-propagated by enumerating other packages its victims maintained. Secondary victims included @mistralai/mistralai and more than 40 packages under the @uipath namespace. @tanstack/react-router alone pulls more than 12 million weekly downloads. A StepSecurity researcher detected the malicious versions within 20 to 26 minutes and opened the tracking issue at 19:46 UTC.

GhostAction: the campaign that never stopped

GitGuardian first documented GhostAction in September 2025, when a workflow that harvests CI/CD secrets was injected into 817 public repositories across 327 GitHub users and exfiltrated at least 3,325 secrets. The new wave ran from August 31 to September 30, 2026, pushing the same style of workflow into 772 public repositories across 373 users and organizations and naming 2,577 secrets as targets, led by 446 SSH and deployment credentials, 218 Azure credentials, 142 container registry credentials, and 106 AWS access keys.

Execution lagged the target list, which is the one piece of good news: of 3,669 workflow runs collected across 605 repositories, GitHub held most for approval, and 336 completed runs exfiltrated 26 secrets from 13 repositories. Cleanup is where the campaign wins: only 124 of the 772 repositories, about 16 percent, had been visibly cleaned by October 5. In 92 cases the attacker added no new workflow at all, instead modifying one a previous wave had planted and nobody removed.

The October 7 and 8 escalation added capability. Per StepSecurity, attackers used the account of Takashi Kitao, author of the 18,400-star game engine pyxel, to push the workflow to 27 repositories starting at 13:20 UTC, then eight hours later the account of Henry Wu, original author of Uber's athenadriver. The new payloads kept Actions secret collection and added a hunt through entire Git histories with git log -p --all, which exposes credentials committed years ago and deleted later. StepSecurity counted 345 repositories in that burst; Socket counted more than 500 accounts committing the workflow to tens of thousands of repositories since October 7. The detection rule is simple: if a workflow named github_actions_security.yml or security-audit.yml appeared in any repository you maintain since August 31, 2026, treat it as a confirmed breach.

Axios in March: a long-lived token beats OIDC

TanStack and Tensorlake abused the trusted publishing path. The March 31, 2026 axios compromise went around it. An attacker took over the maintainer's npm account and published two backdoored releases of a library with over 100 million weekly downloads directly through the npm CLI using a long-lived access token. Both pulled in a phantom dependency never imported by axios code, whose only job was to run a postinstall script that dropped a cross-platform remote access trojan. Exposure ran about three hours overnight, and Huntress saw at least 135 endpoints in its partner base contact the attacker's command and control infrastructure.

The consequential part is configuration. The maintainer had OIDC Trusted Publishing enabled on the 1.x branch, but the publish workflow also passed NPM_TOKEN as an environment variable, and when both are present npm uses the token. That made the long-lived credential the effective authentication method for every publish. The maintainer wrote in GitHub issue #10604: "im trying to get support to understand how this even happened. i have 2fa / mfa on practically everything." Google Threat Intelligence Group linked the campaign to a suspected North Korean actor, UNC1069.

The numbers: 56 attacks, one every three days

StepSecurity's twelve-month total is the cleanest available measure, because it counts malicious releases only and excludes ordinary vulnerability disclosures: 56 confirmed incidents across npm, PyPI, RubyGems, Composer, and crates.io. In the six months from August 2025 through January 2026 the count was 6. Since February 2026 it is 50.

The largest single campaign was TeamPCP's five-day run from March 19 to 24, 2026, which poisoned the Trivy GitHub Action at 76 of its 77 version tags, the Checkmarx KICS Action, the telnyx PyPI package with a stealer hidden inside a WAV audio file, and LiteLLM, a widely used library for routing requests across model providers. When CloudSEK published the victim dataset and StepSecurity analyzed it, the totals were 78,330 secrets stolen from 2,186 organizations, including 92 public companies worth a combined $6.2 trillion in market capitalization.

Worms turned this from a series of incidents into a compounding problem. Shai-Hulud compromised more than 500 npm packages in September 2025 by using each victim's stolen token to infect everything they could publish. CanisterWorm spread backdoors across npm in March 2026, Miasma forced Microsoft to disable 73 repositories in June 2026, and ChainDrop arrived in August 2026 as a Bun-loaded worm using an Ethereum smart contract as a dead drop for its command and control address. The report also notes a shift in who is doing this: attacks that once required state-level resources can now be run by one person with an AI coding agent.

What actually reduces the blast radius

The defenses that work are unglamorous and mostly about treating installation as execution. Set ignore-scripts=true and pin exact versions, because a preinstall or postinstall hook needs no user interaction to run. Pin GitHub Actions to full commit SHAs instead of tags, since tags are mutable references an attacker can repoint for every consumer at once, the mechanism behind the Trivy tag poisoning. Treat a provenance attestation, an SBOM entry, or a Sigstore signature as a build-integrity signal rather than a safety signal. Put detection where code actually executes, on developer machines and inside runners, with egress controls that can stop the callback. Treat any host that installed an affected version as fully compromised and rebuild it rather than cleaning it, because a payload that self-propagates and plants persistence in .claude and .vscode directories is not reliably removable.

Most of all, update the runbook order: find persistence, remove it, then rotate credentials, then verify, then rebuild if you cannot prove the machine is clean. The Tensorlake hostage token exists because attackers now expect defenders to rotate first. The organizations that came through 2026's worst incidents intact are the ones that assumed the trusted package was the attack surface, not the defense.

Sources