I was doing a routine npm install on a Tuesday morning.
Nothing unusual. Same command I've typed thousands of times. Same packages I've used in every project for two years.
Then I saw something in the terminal that made me stop.
A repository had appeared in my GitHub account that I had never created. Named "Shai-Hulud." Containing my npm tokens. My GitHub personal access token. My AWS credentials.
All of them. Public. For anyone to see.
I hadn't been hacked. I hadn't clicked a phishing link. I hadn't done anything wrong.
I had just run npm install.
What Actually Happened — The Attack Nobody Explained Properly
In the second half of 2025, the JavaScript ecosystem was hit by the most sophisticated supply chain attacks in its history. Three separate campaigns. Millions of developers affected. And somehow, most of the developers I talk to have never heard of any of them.
Let me explain what actually happened — in plain English.
September 8, 2025 — The Chalk and Debug Compromise
Attackers used social engineering to steal credentials from package maintainers. Then they updated 18 popular packages — including Chalk and Debug — with an injected malicious payload designed to silently intercept cryptocurrency activity and manipulate transactions.
Chalk and Debug. Two packages that are in virtually every JavaScript project ever written.
Together, these packages are downloaded an estimated two billion times each week. Even with rapid response from the maintainer and npm, the couple of hours that the compromised versions were available could have led to significant exposures.
Two billion downloads per week. Two hours of exposure. Do the math on how many projects were potentially affected.
September 14, 2025 — The Shai-Hulud Worm
The Shai-Hulud worm was the first wormable supply chain malware in npm history.
This is the one that should have made front-page news everywhere.
The Shai-Hulud campaign executes a multi-stage payload that steals credentials from the affected developer machine. If the payload achieves GitHub access, it then publishes the repository Shai-Hulud, which contains all exfiltrated secrets, and self-propagates by poisoning other npm packages in the project.
It didn't just steal your credentials. It used your credentials to infect every package you maintain — turning you into an unwilling participant in spreading the attack further.
November 2025 — Shai-Hulud 2.0
The Shai-Hulud 2.0 campaign was significantly wider in scope, affecting tens of thousands of GitHub repositories — including over 25,000 malicious repositories across about 350 unique users. This campaign introduced a far more aggressive fallback mechanism which could attempt to destroy a user's home directory.
It could destroy your home directory.
Not steal from it. Destroy it.
The Part That Should Scare Every Developer
Here's what makes these attacks different from every attack that came before.
The attack chain begins with a single, seemingly innocuous command: npm install. When a developer installs a compromised package, the malicious code executes during the installation process itself — even before the installation is complete. This happens silently in the background, giving the developer no immediate indication that anything is wrong.
You don't click a link. You don't open a suspicious email. You don't download anything unusual.
You run npm install — the most common command in JavaScript development — and your machine is compromised before the command even finishes.
The attackers cleverly hide their malware within a preinstall script in the package's package.json file. Pre-install and post-install scripts are a standard feature of npm that allows package maintainers to run code before or after a package is installed.
The feature that makes npm packages so convenient — lifecycle scripts — is exactly the feature being used to attack you.
What The Malware Actually Steals
Once it's on your machine, here's what Shai-Hulud looks for:
The malware is programmed to hunt for: GitHub Tokens (full access to your repositories), Cloud Service Keys (AWS, GCP, Azure — keys to your entire infrastructure), and npm Publish Tokens (used to spread the attack further to packages you maintain).
Then it gets worse.
The malware programmatically creates a new public GitHub repository named "Shai-Hulud" under the victim's account and commits the stolen secrets to it, exposing them publicly. Using the stolen npm token, the malware authenticates to the npm registry as the compromised developer. It then identifies other packages maintained by that developer, injects malicious code into them, and publishes the new, compromised versions to the registry.
Your secrets. Published publicly. Under your own GitHub account.
And then your packages — the ones used by other developers who trust you — become the next attack vector.
How to Check If You Were Affected Right Now
Before we get to prevention — check if you're already compromised.
Step 1 — Check for the Shai-Hulud repository:
# Go to github.com and look for a repository named:
"Shai-Hulud" or "Sha1-Hulud: The Second Coming"
# If it exists under your account — you were compromised
Step 2 — Check for malicious GitHub Actions:
# In your repositories, look for:
.github/workflows/shai-hulud-workflow.yml
.github/workflows/shai-hulud.yaml
# If these exist — rotate ALL your secrets immediately
Step 3 — Check your npm publish history:
npm access list packages <your-username>
# Look for unexpected versions published
# in September or November 2025
Step 4 — Audit recent package downloads:
# Check if you installed these packages during attack windows:
# - chalk/debug: Sept 8, 2025 (13:16–15:15 UTC)
# - @ctrl/tinycolor: Sept 14-15, 2025
# - Shai-Hulud 2.0 packages: Nov 24-25, 2025
If you find anything — rotate every credential you have. npm tokens, GitHub PATs, AWS keys, all of it. Immediately.
How to Protect Yourself Going Forward
Here's the practical part. Five things you can do right now:
1. Enable npm Provenance Checking
# Add to your .npmrc
audit=true
audit-level=moderate
# Run before every install
npm audit
2. Disable Lifecycle Scripts for Untrusted Packages
Most supply chain attacks rely on preinstall and postinstall scripts to execute their malicious payloads. You can instruct your package manager to ignore these scripts entirely.
# For a single install (safer for unknown packages)
npm install --ignore-scripts
# For pnpm users — even better protection
# Create .npmrc in your project root:
ignore-scripts=true
3. Lock Your Dependencies — Actually Lock Them
# Commit your lockfile — always
git add package-lock.json
git commit -m "Lock dependencies"
# Use exact versions for critical packages
npm install chalk@5.3.0 --save-exact
# Never run npm update blindly
4. Add a "Cooldown Period" for New Package Versions
The September 2025 npm supply chain attack saw malicious package removal within about 2.5 hours, while Shai-Hulud 2.0 took about 12 hours.
This means: if you wait 24 hours before updating to a new package version, you're protected from the majority of supply chain attacks. The community will have caught it before you install it.
// package.json — pin to known good versions
{
"dependencies": {
"chalk": "5.3.0", // exact version — not ^5.3.0
"debug": "4.3.4" // exact version — not ~4.3.4
}
}
5. Rotate Credentials Regularly and Use Minimal Scope
# Create npm tokens with minimal scope
npm token create --read-only # For CI that only reads
npm token create --cidr-whitelist=10.0.0.0/8 # IP restricted
# Never use your personal npm token in CI
# Create automation tokens with limited permissions
The Bigger Picture — Why This Keeps Happening
Here's the uncomfortable truth about why these attacks succeed.
The npm ecosystem runs on trust. When you run npm install, you're trusting that every package in your dependency tree — including packages your packages depend on — was published by someone with good intentions, with secure credentials, without being compromised.
That's a lot of trust.
2025 proved that npm can host worms, that developer toolchains can be turned against us, and that even the most trusted packages can betray users overnight. The defense isn't a single vendor control — it's identity hardening, script minimization, CI egress discipline, attestations and fast incident response.
No single tool protects you. It's a stack of habits.
The developers who weren't affected by Shai-Hulud 2.0? In some cases, they weren't affected not because they had robust defenses — but because they didn't run npm install or npm update during the attack window. Luck isn't a security strategy.
Luck isn't a security strategy.
Your Action Plan — Do This Today
Immediate (next 30 minutes):
☐ Check GitHub for "Shai-Hulud" repository
☐ Check repos for shai-hulud-workflow.yml
☐ Run npm audit on active projects
This week:
☐ Add --ignore-scripts to CI pipelines
☐ Pin critical dependencies to exact versions
☐ Rotate npm tokens and GitHub PATs
☐ Enable 2FA on npm account if not already
Ongoing:
☐ Wait 24h before updating to new package versions
☐ Review package changelogs before updating
☐ Subscribe to npm security advisories
The Command That Should Scare You
Every developer reading this has typed it thousands of times.
npm install
Four years ago, that command was just convenient.
In 2025, it became a potential attack vector.
The ecosystem is working on fixes — provenance attestations, better monitoring, faster response times. The community is taking this seriously.
But until those fixes are universal, the only thing standing between your credentials and an attacker is your own habits.
Change your habits. Before you need to.
Have you checked your GitHub account for the Shai-Hulud repository? Drop a comment below — especially if you were affected or if you've added security measures to your workflow that others should know about. 👇
Heads up: AI helped me write this.But the research, the analysis, and the genuine concern about developer security are all mine — AI just helped me communicate them better. I believe in being transparent about my process! 😊
Top comments (0)