Security Digest · Sep 15, 2025 · Malicious package · Library
Shai-Hulud: Self-Replicating Worm Hits 500+ npm Packages
Shai-Hulud stole npm, GitHub and cloud secrets and republished 500+ packages incl. @ctrl/tinycolor and CrowdStrike's. Removed. Verdict: check exposure.
Our verdict
Check exposure
The worm's packages were removed in September 2025, but every machine that installed one handed over its npm, GitHub and cloud credentials, so the open question is whether you rotated them and removed the backdoor workflow.
Who must act: Anyone whose developer machines or CI installed an affected package version between Sep 14 and Sep 16, 2025, and any org with a shai-hulud branch, shai-hulud-workflow.yml file or public Shai-Hulud repository.
Who can relax: Teams whose lockfiles and caches contain none of the affected versions and whose GitHub orgs show no Shai-Hulud artifacts; Windows-only installs were skipped by the payload.
- Affected
- @ctrl/tinycolor 4.1.1 and 4.1.2
CrowdStrike npm packages published by crowdstrike-publisher during the campaign
500+ other package versions listed by Socket and StepSecurity (Sep 14-16, 2025) - Fixed in
- Compromised versions removed from npm; npm now blocks uploads matching the worm's IoCs
Pin to releases published before Sep 16, 2025 (CISA) - CVSS
- Not scored
- EPSS
- n/a
- CISA KEV
- Not listed
- Exploitation
- Exploited in the wild
- Severity
- Critical
What to do
- Check lockfiles and caches against a published affected-package list (e.g. npm ls @ctrl/tinycolor) including nested dependencies.
- Search every GitHub org for a shai-hulud branch, .github/workflows/shai-hulud-workflow.yml and public repositories named Shai-Hulud; delete them after preserving evidence.
- On any machine that installed an affected version, rotate npm tokens, GitHub PATs, SSH keys, AWS/GCP/Azure credentials and CI secrets.
- Check your own npm packages for versions you did not publish and deprecate them.
- Move publishing to npm trusted publishing or short-lived granular tokens with phishing-resistant 2FA, and block outbound traffic to webhook.site from CI.
How to check if you are affected or compromised
- npm ls @ctrl/tinycolor; compare package-lock.json against a published affected list
- find . -name bundle.js -exec shasum -a 256 {} + and compare with published hashes such as 46faab8ab153fae6e80e7cca38eab363075bb524edd79e42269217a083628f09
- Search GitHub for shai-hulud-workflow.yml files, shai-hulud branches and Shai-Hulud repositories; review CloudTrail/GCP audit logs for secret-manager reads during installs.
- Review npm publish history of packages you maintain for unexpected versions on Sep 14-16, 2025.
What happened#
Shai-Hulud was the first npm malware that spread itself at scale. Socket logged the first compromise at 17:58 UTC on September 14, 2025. Waves of new releases continued through September 16, the largest being nearly 100 packages at 01:14 UTC that day. The best-known early victim was @ctrl/tinycolor, which has more than 2 million weekly downloads. Versions 4.1.1 and 4.1.2 were trojanized, and StepSecurity reported the incident publicly on September 15. Packages published by CrowdStrike's crowdstrike-publisher npm account were hit in a later wave, with the same malware.
Each infected package ran a roughly 3.6 MB bundle.js at install time. On Linux and macOS (it skips Windows), the script downloaded the legitimate TruffleHog scanner and searched the filesystem for secrets. It also dumped process.env and listed AWS Secrets Manager and GCP Secret Manager entries. It uploaded what it found to a new public GitHub repository named "Shai-Hulud" and sent data to a webhook.site endpoint. For persistence, it pushed a shai-hulud branch with .github/workflows/shai-hulud-workflow.yml to repositories it could write to, so that later runs would leak toJSON(secrets). To spread, it used the victim's npm token to find up to 20 of that maintainer's other packages and republish them with the payload. Socket counted seven versions of the malware. CISA confirmed more than 500 compromised packages and named GitHub PATs and AWS, GCP and Azure keys as the targets.
Who is affected#
Any developer laptop or CI runner that ran npm install and resolved one of the affected versions during the campaign. Socket's list has 526 package-version entries, and StepSecurity's table had 195 when it was published. Both are the lists to check against. The risk is greater if the installing machine held an npm publish token, because that turned the victim's own packages into new carriers. No CVE was assigned to the worm, and it is not in CISA KEV.
Do you really need to act?#
Yes, if you installed an affected version. Otherwise, mostly no. Removing the package does not undo the theft, because the damage happened at install time. GitHub says it removed more than 500 packages and now blocks uploads that match the worm's indicators of compromise, which stopped the spread. But any credentials taken in September 2025 that were never rotated are still exposed, and the backdoor workflow keeps leaking secrets wherever it was merged or left on a branch that runs. For teams with no affected versions in lockfiles or caches, the useful response is structural. GitHub's plan restricts publishing to 2FA-protected local publishes, granular tokens with a seven-day lifetime, and trusted publishing. It also deprecates classic tokens and TOTP 2FA in favor of FIDO.
What to do now#
- Check lockfiles, including nested dependencies, and artifact caches against the Socket or StepSecurity lists. For example, run
npm ls @ctrl/tinycolor. - Search your GitHub organizations for
shai-hulud-workflow.yml, ashai-huludbranch and repositories named Shai-Hulud. Keep evidence, then remove them. - On any affected machine, rotate npm and GitHub tokens, SSH keys, cloud credentials and CI secrets.
- Audit the publish history of packages you maintain and deprecate any versions you did not publish.
- Follow CISA's guidance. Pin to releases from before September 16, 2025 while investigating, require phishing-resistant MFA, block
webhook.siteegress, and turn on secret scanning and branch protection.
How to tell if you were hit#
Hash any bundle.js in node_modules and compare it with the published SHA-256 values. One example is 46faab8ab153fae6e80e7cca38eab363075bb524edd79e42269217a083628f09, and Socket lists all seven. Look for TruffleHog running with filesystem /, npm publish --force, or GitHub API calls during installs. Check CloudTrail and GCP audit logs for secret-manager reads at install time.
Timeline#
- — First compromise at 17:58 UTC. GitHub is notified.
- — StepSecurity discloses the @ctrl/tinycolor compromise and more than 40 other packages.
- — Largest burst at 01:14 UTC. CrowdStrike packages are affected. npm removes the packages.
- — GitHub announces its npm hardening plan.
- — CISA alert on more than 500 compromised packages.
Sources
Original sources first: vendor and project advisories, CVE and government records, the discoverers’ write-ups. Every claim above links to one of these. See how the Security Desk works.
Original and primary sources
- CISA — Widespread Supply Chain Compromise Impacting npm Ecosystem cisa.gov
- GitHub Blog — Our plan for a more secure npm supply chain github.blog
- Socket — Ongoing supply chain attack targets CrowdStrike npm packages socket.dev
- StepSecurity — @ctrl/tinycolor and 40+ npm packages compromised stepsecurity.io