Earlier this week, attackers published two poisoned versions of axios to npm. Versions 1.14.1 and 0.30.4 now inject a dependency called plain-crypto-js@4.2.1, a package that didn’t exist 24 hours ago. It’s a cross-platform remote access trojan. It targets macOS, Windows, and Linux. It deletes itself after execution.
axios has over 100 million weekly downloads. It’s in practically every Node.js project that makes HTTP requests.
The downstream risk of the attack is still active. If you haven’t already, pin your axios version and audit your lockfiles. Don’t upgrade. If you installed the compromised version, assume full system compromise and rotate every credential on the affected machine.
We’ll say more about remediation below. But first, we need to talk about why this keeps happening.
This Wasn’t Clever. It Was Inevitable.
The attacker compromised the npm account of a lead Axios maintainer, changed the email to a ProtonMail address, and published the malicious versions manually via npm CLI. No corresponding GitHub commits exist. The entire CI/CD pipeline was bypassed.
The malicious dependency doesn’t touch a single line of axios source code. It just runs a postinstall script. That script detects your operating system, drops a platform-specific RAT (Remote Access Trojan) payload, contacts a command-and-control server, then erases every trace of itself. If you inspect node_modules afterward, everything looks clean.
This is not a novel technique. Postinstall hooks have been the preferred attack vector for npm malware for years. The Copay wallet hack in 2018 used the same basic approach. The Shai-Hulud worm stole 400,000 developer secrets via postinstall scripts just last year. The Chalk and Debug compromises in September targeted maintainer accounts with phishing.
We keep watching the same movie. The villain uses the same playbook. And the ecosystem keeps pretending the next patch will fix it.
It won’t.
The Problem Is Ambient Authority
Here’s what few in the npm remediation threads is saying: the reason a single postinstall script can steal your SSH keys, cloud tokens, and credentials is that every npm package runs with the full authority of the developer who installs it.
That’s ambient authority. It means any package you install can read any file your user account can read. It can make network requests to any server. It can execute shell commands. It can access every secret on your machine.
axios is an HTTP client. It needs network access. It does not need to read your filesystem, execute shell commands, or write to system directories. But npm gives it all of that anyway, because npm has no mechanism to do otherwise.
This is the architectural flaw. Not the compromised maintainer account. Not the missing two-factor authentication. Not the lack of npm publish verification. Those are symptoms. Ambient authority is the disease.
What Endo and LavaMoat Actually Do About This
We built Endo and LavaMoat specifically to address this class of attack at the architectural level. Not with better scanning. Not with faster detection. With a fundamentally different security architecture.
LavaMoat is an enhancement to your package manager that runs applications and loads libraries in a world that is locked down by default. While privilege exceptions are supported, packages don’t get to just run using arbitrary authority from the user.
LavaMoat’s allow-scripts disables postinstall scripts by default across your entire dependency graph. New packages don’t get to run install scripts unless you explicitly approve them. If plain-crypto-js had shown up in a LavaMoat-protected project, its postinstall hook would never have executed. Full stop.
This alone would have neutralized today’s axios attack.
But LavaMoat goes further. At runtime, it wraps every package in an SES Compartment and enforces a policy that specifies exactly what each dependency can access. An HTTP client gets network access. It doesn’t get fs. It doesn’t get child_process. It doesn’t get execSync. Even if a dependency is compromised, even if malicious code is injected, the code must be considerably more sophisticated and targeted to reach the capabilities it needs to do damage.
This is the Principle of Least Authority applied to the JavaScript dependency graph. It’s the same security model that protects tens of millions of MetaMask users today. It’s the foundation of Agoric’s smart contract platform, where anonymous developers deploy code that handles billions of dollars.
The security properties aren’t theoretical. They’re in production. They’ve been in production for years protecting hundreds of billions of dollars in transactions.
What You Should Do Right Now
Immediate (next hour):
Check whether you have compromised versions installed. Run this in your project root:
grep -r "axios.*1\.14\.1\|axios.*0\.30\.4\|plain-crypto-js" package-lock.json
Also check if the malicious dependency was installed:
ls node_modules/plain-crypto-js/
If you find either, downgrade to axios@1.14.0 (for 1.x) or axios@0.30.3 (for 0.x). Remove the node_modules/plain-crypto-js directory. Rotate all credentials on the affected system. Check for outbound connections to sfrclak.com.
This week:
Add @lavamoat/allow-scripts to your project. It configures your package.json to disable install scripts by default and lets you maintain an explicit allowlist. This eliminates the most common npm attack vector with minimal friction.
npx @lavamoat/allow-scripts setup
Run --ignore-scripts as standard practice in CI/CD.
This quarter:
Adopt LavaMoat runtime protection. Generate policies, review them, enforce them. It’s not zero effort, but it’s the difference between hoping your dependencies are safe and knowing they can only do what you’ve authorized.
Documentation: lavamoat.github.io GitHub: github.com/LavaMoat/LavaMoat
We Shouldn’t Need a Crisis Every Quarter
In September, it was Chalk and Debug. In December, the Shai-Hulud worm. Now axios. Each incident follows the same pattern: maintainer account compromised, malicious code injected, postinstall script exploited, millions of developers exposed.
After each one, the ecosystem runs through the same cycle. Emergency advisories. Credential rotation. Calls for better npm security features. Mandatory 2FA. Trusted publishing. Those measures help at the margins. They raise the cost of attack. But they don’t change the fundamental problem.
The fundamental problem is that npm’s security model gives every package the keys to your entire machine, and no amount of scanning or detection changes that. Socket flagged plain-crypto-js within six minutes of publication. That’s impressive. But six minutes is enough time for a postinstall script to exfiltrate every secret on a developer’s workstation.
Detection is necessary. It is clearly not sufficient.
What’s sufficient is an architecture where each code module runs in a compartment with only the authority it needs. Where a malicious postinstall hook can’t run at all unless explicitly approved. Where even if an attacker gets code execution inside your dependency graph, the blast radius is bounded by its limited authority.
That architecture exists. It’s called Endo. LavaMoat puts it in the hands of any JavaScript development team, with support to apply it to existing code bases.
The axios attack will pass. The next one is already being planned. The question is whether you’ll still be relying on detection and luck, or whether you’ll have adopted the security model that makes this class of attack structurally impossible.
Join the build. Endo and LavaMoat are open source and we need more hands. Security researchers, tooling developers, anyone who thinks detection-after-the-fact isn’t good enough.
→ github.com/endojs/endo · github.com/LavaMoat/LavaMoat · Matrix
Building something that can’t afford another axios? The Decentralized Cooperation Foundation helps organizations integrate object-capability security into production systems. Reach out for more information dcfoundation.io
Endo: github.com/endojs/endo LavaMoat: github.com/LavaMoat/LavaMoat HardenedJS: hardenedjs.org