NPM-SHAI-HULUD-2025
npm · @ctrl/tinycolor, ngx-bootstrap, ng2-file-upload (+500 more)
Summary
Shai-Hulud, in September 2025, was the moment the npm ecosystem's oldest nightmare came true: a worm that spreads by itself. It began with a wave of compromised packages, the most prominent being @ctrl/tinycolor (over two million weekly downloads), and from there it did something no npm attack had done before. When its malware ran on a developer's machine, it hunted for every credential it could find, then used the developer's own npm token to republish itself into all of their other packages automatically, with no attacker involvement, jumping from maintainer to maintainer like an infection. More than 500 packages were compromised, including some from CrowdStrike. It is the first true npm worm (tracked as GHSA-6m4g-vm7c-f8w6 and GHSA-f3v2-259r-f6jc), the template for the more aggressive Second Coming that followed weeks later, and the ancestor of an entire 2026 lineage that ended with the worm's code being open-sourced for anyone to reuse.
How it happened
Named for the sandworm in Dune, Shai-Hulud began on 14 September 2025 with a first burst of compromised packages (the earliest observed was rxnt-authentication; the highest-profile was @ctrl/tinycolor) and then ran a self-sustaining loop. The first packages were seeded with credentials harvested earlier: most analysts trace the seed to the August 2025 s1ngularity attack on the Nx build system, which stole maintainer npm tokens that were never rotated, alongside a parallel phishing campaign using a spoofed npmjs.help domain. (s1ngularity was itself a landmark, the first supply-chain attack to weaponise developers' local AI command-line assistants, invoking the installed tools to crawl the filesystem for secrets.) Same-actor attribution between the two is still treated as an open question rather than settled fact.
When the malware executed in a developer's environment, it harvested that developer's secrets, npm tokens, GitHub personal access tokens, and AWS, GCP, and Azure credentials, using the TruffleHog secret scanner to find them. It exfiltrated those secrets to an attacker webhook and to public GitHub repositories it created, forced some victims' private repositories public, and established persistence by planting a malicious GitHub Actions workflow (shai-hulud-workflow.yml).
The part that made it historic was self-replication. Using the stolen npm token, the malware authenticated to npm and automatically republished trojanized versions of every package the victim maintained, spreading exponentially with no operator involvement at all. Each compromised maintainer became a new launch point, so the worm grew on its own. That is what makes it a worm rather than an ordinary one-shot supply-chain attack, and Wiz called it the first successful self-propagating attack in the npm ecosystem.
The damage
More than 500 packages were caught up in it (security firm Socket catalogued 526 compromised package-and-version entries), including roughly ten packages from the security vendor CrowdStrike, and developer and cloud credentials were harvested at ecosystem scale. The deeper damage was structural: an npm attack that propagates on its own means the list of affected packages grows exponentially rather than staying fixed, which is a fundamentally harder problem to contain. CISA issued a federal alert on 23 September 2025, and the incident forced a permanent change to how npm publishing works. On 9 December 2025 GitHub and npm revoked all legacy classic npm tokens, replaced long-lived tokens with short-lived session tokens, and pushed OIDC-based trusted publishing as the recommended path. That reform is the direct fingerprint of this worm.
The lineage: from one worm to open-source malware
Shai-Hulud did not stop. Weeks later it returned, nastier and at far greater scale, as the Second Coming in November 2025, reaching more than 25,000 repositories and adding a destructive fallback that tried to wipe a victim's home directory. Through early 2026 the family kept mutating, and in May 2026 a group calling itself TeamPCP did the thing that changed the threat permanently: they open-sourced a streamlined variant, Mini Shai-Hulud, publishing the worm's code publicly under the banner "Shai-Hulud: Open Sourcing The Carnage" and even running a contest for the largest attack built with it.
Open-sourcing converted a single-actor campaign into a reusable technique. Within weeks, copycats and unrelated actors were running near-exact copies, and the first major incident built from the leaked code, the @redhat-cloud-services compromise nicknamed Miasma in June 2026, did something the original could not: it published malicious packages carrying valid build provenance by abusing Red Hat's legitimate trusted-publishing pipeline. The worm that began as one actor's tool became a commodity, and attribution collapsed along with it.
Why Shai-Hulud still matters
It is the first self-replicating npm worm, a genuine watershed. Before it, npm supply-chain attacks were one-shot: poison a package and wait. Shai-Hulud weaponised stolen publish tokens to spread itself, turning every compromised maintainer into a spreader, and its descendants then made the technique public property. The defences target that mechanism directly: use short-lived, narrowly scoped publish tokens or OIDC trusted publishing so a stolen token cannot be reused to self-propagate; require phishing-resistant 2FA on maintainer accounts; run installs and CI in isolated, least-privilege environments with no standing cloud credentials; disable install scripts where feasible; and scan for and rotate leaked secrets fast.
How to fix it
- Treat every machine that ran an infected package as fully compromised: rotate npm, GitHub, and cloud credentials immediately, and revoke the worm's published versions.
- Search GitHub for the worm's exfiltration repositories and webhooks to find which secrets leaked, and check your own packages for unauthorized republished versions.
- Remove the malicious GitHub Actions workflow it added for persistence, and rebuild from a clean lockfile pinned to known-good versions.
How to avoid it
- Use short-lived, narrowly scoped publish tokens or OIDC trusted publishing, so a stolen token cannot be reused to self-propagate, the worm's core mechanism.
- Require phishing-resistant 2FA on maintainer and publisher accounts.
- Run installs and CI in isolated, least-privilege environments with no standing cloud credentials, and disable install scripts where feasible.
- Scan continuously for leaked secrets and rotate fast, and pin dependencies so a freshly poisoned version cannot flow straight into your builds.
References
- https://socket.dev/blog/ongoing-supply-chain-attack-targets-crowdstrike-npm-packages
- https://www.wiz.io/blog/shai-hulud-npm-supply-chain-attack
- https://www.stepsecurity.io/blog/ctrl-tinycolor-and-40-npm-packages-compromised
- https://unit42.paloaltonetworks.com/npm-supply-chain-attack/
- https://www.cisa.gov/news-events/alerts/2025/09/23/widespread-supply-chain-compromise-impacting-npm-ecosystem
- https://github.blog/changelog/2025-12-09-npm-classic-tokens-revoked-session-based-auth-and-cli-token-management-now-available/
Related vulnerabilities
All Supply chain →- CRITICALNPM-REDHAT-MIASMA-2026
In June 2026 the npm supply-chain worm finally produced something genuinely new and frightening: malicious packages that were signed and carried valid build provenance. Attackers used a compromised GitHub account inside Red Hat's own organisation to publish trojanised versions of 31 packages in the @redhat-cloud-services namespace through Red Hat's legitimate CI pipeline, so the poisoned releases arrived with authentic attestations proving they were built by the real build system. The payload, nicknamed Miasma, was a lightly re-skinned copy of Mini Shai-Hulud, a worm that a group called TeamPCP had open-sourced for anyone to reuse weeks earlier. No Red Hat customers were harmed, because Red Hat strips install scripts before deployment, but the permanent lesson is uncomfortable: a signature proves where a package was built, not that the build was clean.
- CRITICALNPM-AXIOS-2026
On 31 March 2026 the single most widely used HTTP client in the JavaScript world was turned into malware for about three hours. Axios carries well over 100 million weekly downloads and sits as a transitive dependency underneath a huge share of the npm ecosystem, so when a North Korea-nexus actor took over the maintainer's account and published two booby-trapped versions, the blast radius was enormous even though the bad versions were live only for one early-morning window. The poisoned releases pulled in a hidden dependency that ran on install and dropped a cross-platform remote access trojan onto developer machines and CI runners. It is the case study in why a few hours of a popular package being compromised is still a global incident, and in why a maintainer's own laptop is now a nation-state target.
- CRITICALNPM-SHAI-HULUD-2-2025
Shai-Hulud is the nightmare the npm ecosystem had long feared: a self-replicating worm. First seen in September 2025 and back in a more aggressive wave around 21-24 November 2025 ("The Second Coming"), it does not just poison one package and wait. When its malware runs in a developer's environment, it harvests every secret it can find, npm tokens, GitHub tokens, cloud keys, then uses those stolen npm tokens to automatically publish itself into other packages the victim maintains, spreading from maintainer to maintainer on its own. The second wave hit more than 25,000 GitHub repositories across roughly 500 compromised accounts, leaked the stolen secrets into public repos, and, if it failed to steal credentials, tried to wipe the victim's home directory. It is the moment supply-chain malware learned to propagate like a biological infection.
- HIGHCVE-2025-30066
tj-actions/changed-files was one of the most widely used GitHub Actions on the planet, wired into the CI pipelines of more than 23,000 repositories just to list which files a pull request touched. On 14 March 2025 it was turned into a weapon. An attacker who had stolen the credentials of the project's bot account rewrote nearly every version tag, from v1 all the way to v45.0.7, so they all pointed at one malicious commit. Any pipeline that pulled the action then ran code that dumped the build runner's memory and printed the secrets it found, AWS keys, GitHub tokens, npm tokens, private keys, straight into the workflow logs. Tracked as CVE-2025-30066, it is the defining modern CI/CD supply chain attack, and a blunt lesson that a version tag is a sticky note, not a lock.
- HIGHCVE-2026-62680
Orval: Generation-time SSRF + remote/local file inclusion via unrestricted $ref
- CRITICALGHSA-93qj-5q5v-3c2h
Trojanized pantheon-agents 0.6.1 and 0.6.2 on PyPI ship a credential stealer (supply-chain account compromise)