Cloud & DevOpsAnalysis
How the April, May and August open-source worms put signed releases on npm and PyPI, and the settings that keep the next one out, 29 April to 7 August 2026.
After the Shai-Hulud worm of September 2025, the advice to package maintainers was to stop publishing with stored tokens. Instead they were told to adopt trusted publishing, where the build system proves who it is to the registry, and to attach provenance to every release.9 In 2026 attackers used that machinery itself. If your company ships software built on JavaScript or Python, three questions follow. What does a signed, attested package still tell you? How does a worm reach your build servers through someone else’s maintainer account? And which settings in your own pipelines would have kept this year’s releases out?
The first wave hit on 29 April. Between 09:55 and 12:14 UTC, poisoned versions of four official SAP packages appeared on npm. They were mbt, which is used in SAP Cloud MTA builds, and three database packages from SAP’s Cloud Application Programming model.2 Together they get about 572,000 downloads a week. The next day the same malicious code showed up in intercom-client on npm and in versions 2.6.2 and 2.6.3 of lightning, the PyTorch Lightning package on PyPI. Wiz and Socket attributed the SAP compromise to a group called TeamPCP.1
On 12 May the same playbook reached TanStack, Mistral AI and UiPath. Orca called it “the third documented wave from TeamPCP”. It counted 373 malicious versions across 169 npm package names and 2 PyPI packages.3 The third wave began on 4 August, when keyv@6.0.0 was published at 09:35 UTC. Within hours the cache libraries around it followed: cacheable, flat-cache, file-entry-cache and cache-manager.45
Each wave reached further: four SAP packages in April, 373 versions in May, more than 2,000 in August
Open-source package compromises in the Shai-Hulud family, 29 April to 6 August 2026 (UTC)
| Date | Event | Detail |
|---|---|---|
| 29 Apr 2026 | SAP npm packages | Four packages poisoned between 09:55 and 12:14 UTC; the three CAP releases had no provenance |
| 30 Apr 2026 | PyTorch Lightning and Intercom | lightning 2.6.2 and 2.6.3 on PyPI; intercom-client on npm; same code |
| 12 May 2026 | TanStack, Mistral AI, UiPath | 373 versions, 169 npm names, 2 PyPI packages, with valid provenance |
| 4 Aug 2026 | keyv and the cache libraries | First release 09:35 UTC; 444 packages and 2,212 versions in under four hours |
| 6 Aug 2026 | Singapore's CSA advisory | Treat affected systems as compromised; rebuild and rotate credentials |
Source: The Hacker News and The Register (April); Orca Security (May); StepSecurity, Datadog Security Labs and Singapore CSA (August) · as of 7 August 2026 · Counts are each source's own and use different units; the August figure is StepSecurity's
A provenance attestation is a signed statement from the build system: this package was built from this repository, at this commit, by this workflow. Under trusted publishing, the workflow gets a short-lived token from the registry instead of holding a stored one. npm says provenance lets you “publicly establish where a package was built and who published a package”. It also says that provenance “does not guarantee the package has no malicious code.”8 This year’s attackers worked in the gap between those two sentences.
In April the warning sign still worked. The SAP database packages were published “without provenance”. The attackers had pushed a modified workflow to a side branch and pulled the publishing token out by hand. SafeDep found why that was possible: the trusted publisher setting “trusted any workflow” in the repository, not just the release workflow on the main branch.2 May closed that gap. The TanStack releases came from the legitimate runner with valid tokens, so they “carry valid npm provenance attestations”.3 In August, keyv@6.0.0 carried genuine SLSA provenance tied to its own release workflow, logged in the public Rekor transparency log.5 StepSecurity put it in one line: “Provenance proves which commit was built. It cannot prove the commit was authorized.”4
A valid attestation answers where and how a package was built; it is silent on whether the code should exist
What npm provenance and trusted publishing establish, read against the April, May and August 2026 releases
What a valid attestation proves
What it cannot prove
Source: npm Docs, Generating provenance statements; Orca Security; Datadog Security Labs; StepSecurity · as of 7 August 2026
A worm needs two things from each machine it lands on: a way to run, and someone’s right to publish. npm’s install scripts give it the first; a maintainer’s laptop or CI runner gives it the second.
Each infected maintainer becomes a publisher: install, harvest, republish, persist
The August 2026 worm's propagation loop, as reconstructed by Datadog and StepSecurity
Install runs the payload
A poisoned release adds a preinstall hook, so the code runs on npm install, before anyone imports it. It fetches the Bun runtime to run itself.
Harvest every secret
It reads 469 file patterns, the whole environment, the GitHub CLI token and cloud secrets. On Linux GitHub Actions runners it reads secrets out of the runner’s memory.
Republish as the victim
It lists every package the stolen npm token can write, injects the hook into each one and uploads it. Datadog found tokens set to bypass two-factor checks.
Persist and punish
It pushes hooks into up to 50 branches that fire in VS Code or Claude sessions. A token monitor runs a payload if the token is revoked. In May, the same kind of daemon was set to wipe the home folder.
Source: Datadog Security Labs (4 August 2026, updated 5 August); StepSecurity (4 August 2026); Orca Security (12 May 2026) · as of 5 August 2026
2,212
malicious npm versions in under four hours on 4 August 2026, by StepSecurity's count
Only 11 packages were seeded by hand. The worm itself republished the other 433 packages and 2,201 versions.4
The arithmetic of that loop explains the scale. The first releases came from the maintainer’s compromised GitHub account; StepSecurity says “no long lived npm token was used at all” for them. Everything after that used stolen credentials: “every publish uses the victim org’s own maintainer credentials.”4 Releases published with a stolen token carry no provenance. The first, workflow-built releases did.5 So a single wave produced both kinds, and no one provenance rule could have caught all of it.
The registry’s own fix is still arriving. In September 2025 GitHub said npm would limit granular publishing tokens to seven days, deprecate classic tokens, “remove the option to bypass 2FA for local package publishing” and disallow tokens by default. It gave no dates.9 The tokens the August worm used still carried a bypass_2fa flag set to true.5
How big was 4 August? It depends on who you ask, and when. StepSecurity reported 444 packages and 2,212 versions in its update at 18:10 UTC that day.4 SafeDep first verified 353 versions across 79 names, then raised its count to 1,684 versions across 420 names in nine organisations. Aikido reported at least 868 packages across 1,381 versions.6 On 6 August Singapore’s Cyber Security Agency put it at “over 1,300” versions, with combined downloads of 2 billion a month.7 Datadog said only that “hundreds” of packages were hit, some with more than 150 million weekly downloads.5
Version counts for the same morning range from about 1,300 to 2,212, depending on who counted and when
Malicious npm package versions reported for the 4 August 2026 worm, by source, 4 to 6 August 2026
Source: StepSecurity (4 Aug, 18:10 UTC); SafeDep and Aikido as reported by The Hacker News (4 Aug); Singapore CSA AD-2026-009 (6 Aug) · as of 6 August 2026 · CSA's figure is a floor: it said over 1,300. Aikido's figure carries no time. These are counts of malicious releases, not of infected machines; do not add them together.
These are snapshots of a moving target, taken at different hours, some by package name and some by version. The Hacker News could not reproduce either broader total from a complete public list, and warned that Aikido’s and SafeDep’s counts “should not be combined.”6
This year’s malicious releases were spotted fast. By 17:40 IST on 4 August, earlier clean releases were back as latest for at least nine of the first packages hit.6 The organisations that got hurt were the ones that installed within those hours. That makes time the cheapest control a package consumer has.
Most of the protection is in settings you already own: delay, pin, narrow who can publish, and wall off CI
Controls against the April, May and August 2026 waves, in the order to apply them
Step 1 of 6
1. Check today
Search lockfiles and CI logs for the affected name and version pairs, including transitive dependencies. Datadog and StepSecurity publish the lists.
Source: StepSecurity; Orca Security; The Hacker News on SafeDep's findings; Singapore CSA AD-2026-009; pnpm 10.21.0 release notes · as of 7 August 2026
Steps 3 and 4 protect you as a consumer; steps 5 and 6 matter if you publish anything, even internal packages. The May wave began with a fork’s pull request that triggered a pull_request_target workflow and poisoned the shared Actions cache. The real release job restored that cache and gave up its publishing token.3 No stored secret was stolen; the pipeline’s own trust was turned against it.
Sources
Related on TechBag: the GitHub Enterprise page covers the platform whose Actions runners and caches sat at the centre of the May wave, along with its secret scanning and dependency review. The GitLab DevSecOps page covers dependency scanning and SBOMs built into the pipeline. The GitHub vendor hub lists the rest of the line.
Disclosure. TechBag is a software reseller: it earns a margin when a reader buys through it, including from vendors named here. The analysis is TechBag’s own; no vendor paid for or saw this piece before publication. Facts are labelled reported, TechBag count or our view.