← Back to Attack Research

Worms in the registry: three 2026 npm and PyPI compromises that stole every cloud credential

A package manager that runs install scripts by default turns a passive download into remote code execution. In 2026, three registry campaigns weaponized that one default to harvest AWS, Azure, GCP, and Kubernetes tokens, and one shipped valid SLSA provenance while doing it. Here is how registry worms work, how to find the affected versions in your build, and the controls that break the loop.

The most dangerous line in your build is one you never wrote. When you install a JavaScript dependency, npm runs the package's preinstall and postinstall scripts by default, with no prompt and no sandbox, on the machine doing the install. That single default converts downloading a package into executing its author's code on your build host, your laptop, or your continuous-integration runner. In 2026, three separate campaigns turned that mechanism into credential-harvesting worms that read cloud and cluster tokens and, in one case, re-published themselves through the accounts they stole. This is CWE-506 (Embedded Malicious Code) meeting CWE-1357 (Reliance on Insufficiently Trustworthy Component) at the exact moment your pipeline trusts the registry the most.

This is about the class, not a single bad package. Registry worms are not clever exploits of a memory bug; they are ordinary software features used exactly as designed, pointed at you. The design in question is automatic install-time script execution, and it is the shared root enabler across every incident below. We describe behavior at the defender level. There is no live payload here, and none is needed to understand why this class is now the fastest way to lose an entire cloud footprint from a single line in a lockfile. Verifiable security.

The one default that enables all three

npm's lifecycle hooks exist for legitimate reasons. Native modules compile, tools drop shims, and packages wire themselves into a project during install. To make that seamless, the client runs the scripts automatically. The problem is that the mechanism does not distinguish a compile step from a credential-exfiltration step. Both are just commands that run with the privileges of whoever typed the install command, which on a build host is frequently the identity that also holds cloud roles, registry publish tokens, and cluster access. A passive download becomes arbitrary code execution with zero user interaction, and it happens before your tests run, before your review, before anything a human would inspect.

PyPI has the same shape through its own build and install path, which is why the class spans both ecosystems. The attacker's economics are simple: publish once, and every machine that installs the package runs the code. If that code can also read a publish token, the package can push a poisoned version of the next package, and the loop becomes a worm.

Three campaigns, one mechanism

Mini Shai-Hulud (attributed to "TeamPCP"), around 11 to 12 May 2026. This npm and PyPI worm compromised roughly 160 to 170 packages, including widely used projects in the TanStack and Mistral AI ecosystems. Its standout property was not stealth but legitimacy: it produced malicious packages that carried valid attestation, published with SLSA Build Level 3 provenance. A pipeline that checked only "does this artifact have provenance" waved it straight through. To be precise about naming, this is a 2026 echo of an earlier lineage; the original Shai-Hulud and its follow-on wave were 2025 events. The version numbers and dates of those earlier incidents are not the same as this one, and conflating them misreads the timeline.

Microsoft durabletask on PyPI, 19 May 2026. Malicious versions 1.4.1, 1.4.2, and 1.4.3 silently pulled a second-stage payload at install time. That payload harvested AWS, Azure, GCP, and Kubernetes credentials along with more than ninety developer-tool configuration files. It exfiltrated through multiple channels, including public GitHub repositories it created using the victim's own stolen tokens, so the data left through infrastructure that looked like the victim's. It added fake-systemd persistence, attempted lateral movement using AWS SSM and kubectl exec, and shipped a Linux wiper as a destructive finale. One poisoned dependency version, and the install host became an incident.

Mastra @mastra/* on npm, 17 June 2026, attributed to Sapphire Sleet (North Korea). A hijacked maintainer account introduced a typosquat of the popular dayjs library named easy-day-js across more than 140 @mastra packages. The typosquat's postinstall hook ran an obfuscated dropper of roughly 4,572 bytes that disabled TLS certificate verification and beaconed to command-and-control. The lesson is that the maintainer account is part of the attack surface: compromise the human, and you inherit the trust every downstream project already placed in their packages.

HOW A REGISTRY WORM CLOSES THE LOOP attacker publishes / hijacks maintainer | v [ package version on registry ] | you run install | lifecycle hook runs AUTOMATICALLY <-- the one default | +--------+---------+ | | read cloud/CI read publish token tokens, configs | | v v push poisoned NEXT package exfil via GitHub / | C2 / SSM / kubectl +--> loop repeats == WORM No user interaction. Execution happens before review.

The worm is not a memory-corruption exploit. It is an install-time script plus a stolen publish token. Illustrative of the class, not any single host.

Why provenance alone is not the fix

The Mini Shai-Hulud wave is the important teacher here, because it defeats the control most teams reached for first. Provenance and attestation answer "was this built by the pipeline it claims," and that is genuinely useful. But an attacker who compromises the pipeline, or the account that drives it, can produce artifacts that are truthfully attested and still malicious. Valid SLSA provenance on a hostile package is not a contradiction; it is the predictable result of trusting build identity while ignoring build behavior. Provenance has to sit next to behavioral checks, not replace them.

Valid provenance on a malicious package is not a contradiction. It is what you get when you verify who built an artifact and never ask what the artifact does at install time.

How to find it in your build

You do not need to detonate anything in production to know your exposure. The signal is in your lockfiles and your install logs, and it is readable today.

Hunt for registry-worm exposure

To prove a suspected package rather than assume it, install the pinned bad version in a disposable, egress-monitored sandbox and observe what the lifecycle hook does: the network it reaches, the credential paths it reads. Never do this on a host that holds real cloud, CI, or registry secrets. The point of the sandbox is that the worm's whole value is the credentials on the box, so you deny it any.

How Celvex catches this

Find. Prove. Fix. Verify.

Find

An SBOM and lockfile sweep flags the affected package and version ranges, then hunts install logs for install-time egress, interpreter-piped downloads, and public-repo creation tied to your build identity.

Prove

In an egress-monitored sandbox, the pinned bad version is installed and its lifecycle hook is observed reaching out and reading credentials. The evidence becomes an Ed25519-signed Proof Capsule, reproducible offline.

Fix

Pin or roll back to known-good versions, rotate every cloud, CI, and GitHub credential exposed to a build host that ran a bad version, and enforce ignore-scripts in CI on egress-restricted builders.

Verify

A fresh sweep confirms clean versions are installed, no fake-systemd units linger, and rotated credentials have replaced the exposed set. The finding closes with the verified-fix event on record.

The durable fix is architectural, not a one-time cleanup. Enforce ignore-scripts in continuous integration so install hooks never run automatically on a builder. Run installs on egress-restricted machines so a hook that does slip through cannot reach its command-and-control or exfiltration channel. And require provenance plus behavioral analysis together, because the Mini Shai-Hulud wave already proved that provenance alone is a check an attacker can satisfy. Treat the maintainer account and the publish token as first-class secrets, because a hijacked account is how the worm gets its first version out.

Verifiable security. Find it. Prove it. Fix it. Verify the fix held. That is what we ship.

Sources

Is a poisoned package version already in your lockfile?

Free Exposure Check, no signup required. We scan your SBOM and lockfiles against the known-bad package and version ranges, hunt your install logs for install-time egress, and ship a signed Proof Capsule for the highest-confidence finding.

Run a Free Scan →