
Axios Was Backdoored for Two Hours and Gave Hackers Full Control of Your Machine
On March 31, 2026, the most-downloaded JavaScript HTTP client was backdoored for two hours. Here is what actually happened, why vibe coders are especially at risk, and exactly what you need to do right now.
At 00:21 UTC on March 31, 2026, someone published axios@1.14.1 to npm. It had a backdoor in it.
Not in the axios source code , that part was clean. The attacker was smarter than that. They slipped in a single fake dependency called plain-crypto-js@4.2.1, and that dependency ran a postinstall script that downloaded a cross-platform remote access trojan to your machine the moment you ran npm install.
If your CI pipeline ran in that window, assume compromise. If you pulled a fresh install between 00:21 and 03:29 UTC, your credentials may already be somewhere you do not want them.
This is what modern supply chain attacks look like. And no, your AI code editor did not warn you about it.
What Actually Happened
The attacker did not find a vulnerability in axios's code. They went after something softer: the npm account of @jasonsaayman, axios's primary maintainer. Somehow they got his credentials , likely through a phishing campaign or a leaked token , and changed the registered email on his account to a Proton Mail address they controlled.
With maintainer access, they published two poisoned versions:
axios@1.14.1at 00:21 UTCaxios@0.30.4at 01:00 UTC
Both versions looked normal from the outside. Same source code. Same API. The only difference was in package.json, where the attacker added plain-crypto-js@4.2.1 as a runtime dependency , a package that had been staged 18 hours earlier with a clean 4.2.0 version to give it a brief legitimate history on the registry.
When npm resolved the dependency tree, it pulled plain-crypto-js, hit its postinstall hook, and executed setup.js. That was the dropper.
CVE Reference
This incident is tracked as SNYK-JS-AXIOS-15850650 (the poisoned axios versions) and SNYK-JS-PLAINCRYPTOJS-15850652 (the malicious dependency). Neither is available on npm anymore, but if you installed during the window, the damage is already done.
The dropper used two layers of obfuscation , reversed Base64 with padding substitution, followed by an XOR cipher with the key OrDeR_7077. Once decoded, it reached out to sfrclak[.]com:8000 and downloaded a platform-specific second-stage payload:
- macOS: A compiled C++ binary dropped to
/Library/Caches/com.apple.act.mond, spoofing an Apple background daemon - Windows: PowerShell copied to
%PROGRAMDATA%\wt.exedisguised as Windows Terminal, with a Registry Run key for persistence across reboots - Linux: A Python RAT written to
/tmp/ld.pyand launched vianohupso it survived the terminal session
All three variants beaconed to the C2 server every 60 seconds. All three could execute arbitrary commands, enumerate your filesystem, and load additional payloads. The macOS and Windows variants supported in-memory binary injection.
After execution, the dropper deleted itself, removed the postinstall entry from package.json, and swapped in a clean manifest file. If you inspected node_modules/plain-crypto-js after infection, you would find no trace it was ever there.
Elastic Security Labs noted significant overlap between the macOS payload and WAVESHAPER, a C++ backdoor attributed by Mandiant to UNC1069, a North Korean threat actor. That detail should sit with you for a minute.
Vibe Coders: You Are the Target
Here is the uncomfortable truth. This attack was not aimed at security engineers who review lockfiles before deploying. It was aimed at the people who type npm install and move on.
There is a generation of developers right now , and I include myself in this at times , who use AI tools to generate entire applications, copy-paste npm install commands from Stack Overflow threads or AI chat responses, and deploy before they have read the README. This workflow is fast. It ships. It is exactly what "vibe coding" describes.
But fast iteration without security awareness is not a feature. It is an attack surface.
The axios attack worked because CI/CD pipelines across thousands of organizations were set up to run npm install (not npm ci) without pinned versions, without lockfile enforcement, and without --ignore-scripts. Three hours. Two malicious package versions. And any pipeline that pulled a fresh install during that window was fully compromised the moment npm finished running.
The Scale Problem
Axios has over 100 million weekly downloads. Even a two-hour malicious window represents an enormous blast radius. The attacker hit both the 1.x and 0.x release branches within 39 minutes of each other. This was not accidental. It was planned.
The vibe coding ethos is real and it produces real things. But the tools you use , npm, GitHub Actions, Vercel deploys , are part of a supply chain. You do not have to become a security expert overnight. But you do have to stop treating npm install like a consequence-free action.
How to Check If You Are Affected
Run this right now.
# Check for the compromised axios versions
grep -E '"axios"' package-lock.json | grep -E '1\.14\.1|0\.30\.4'
# Check for the malicious dependency
npm ls plain-crypto-js
# Search node_modules directly
find node_modules -name "plain-crypto-js" -type dIf you are on Bun:
grep -E 'axios' bun.lock | grep -E '1\.14\.1|0\.30\.4'
grep 'plain-crypto-js' bun.lockAlso look for RAT artifacts on the system itself:
| Platform | Artifact |
|---|---|
| macOS | /Library/Caches/com.apple.act.mond |
| Windows | %PROGRAMDATA%\wt.exe |
| Linux | /tmp/ld.py |
| Network | Outbound connections to sfrclak[.]com or 142.11.206.73:8000 |
If you find any of these, the machine was compromised. Do not attempt to clean it. Rebuild from a known snapshot.
How to Fix It and Stay Protected
If you are not affected, great. Here is what to do anyway.
Pin axios to a known safe version
Any version except 1.14.1 and 0.30.4 is clean. In your package.json, pin to 1.14.0 or earlier. Do not use a version range that would silently pull the next release on install.
{
"dependencies": {
"axios": "1.14.0"
}
}Switch CI from npm install to npm ci
npm install can update your lockfile. npm ci enforces it. This single change would have protected most organizations from this attack.
# In your CI pipeline, replace:
npm install
# With:
npm ciAdd --ignore-scripts to CI installs
The entire attack lived in a postinstall hook. Disabling lifecycle scripts in CI eliminates this class of attack entirely.
npm ci --ignore-scriptsBe aware this breaks packages that legitimately need postinstall steps (native addons, for example). Test your build after adding this flag.
Block plain-crypto-js at the registry level
Add plain-crypto-js to your organization's package blocklist. In npm Enterprise and many private registry setups, you can explicitly deny packages.
Run a security scan today
npm install -g snyk
snyk auth
snyk testSnyk's database includes entries for both CVEs. If you have any projects that pulled the affected versions, it will flag them.
If you already found the compromised version:
- Isolate the machine immediately. Do not rotate credentials from the affected system , the RAT may be watching.
- Rotate everything from a clean machine. API keys, SSH keys, GitHub tokens, cloud credentials, npm tokens. Revoke and reissue, do not just change values.
- Check your CI/CD logs for March 31, 2026 UTC. Every pipeline that ran
npm installin that window needs investigation. - Block egress to
sfrclak[.]comand142.11.206.73at the network level. - Rebuild the environment. Compromised machines cannot be trusted.
If In Doubt, Rotate
A stolen API key is the attacker's best tool. Rotate constantly, not just when you think you have been hit. The cost of rotating credentials is hours. The cost of a breach is days, sometimes a company.
The Bigger Pattern Nobody Wants to Talk About
This is not the first time a legitimate npm package was hijacked through a compromised maintainer account. It happened to ESLint's Prettier plugin. It happened to ua-parser-js in 2021. It happened to the Shai-Hulud campaign, which compromised over 600 packages in a single operation.
The common thread is not a clever 0-day or an advanced technique. It is social engineering plus an ecosystem that gives postinstall scripts full system access by default.
You should also know that two other packages were shipping the same payload: @qqbrowser/openclaw-qbot@0.0.130 and @shadanai/openclaw versions 2026.3.31-1 and 2026.3.31-2. The same C2 infrastructure. The same RAT. The axios compromise may have been the main show, but it was not the only stage.
The open source ecosystem runs on trust. Maintainers give their time, often for free, to build tools that power billions of dollars of software. That trust is also the attack surface. Protecting it requires more than good intentions , it requires 2FA on npm accounts, hardware keys for publishing access, and lockfile hygiene that most projects still do not have.
And maybe, just maybe, before you vibe-code your next startup on a stack of unaudited dependencies, take ten minutes to check what you are actually installing.
Did this affect your setup, or did you catch it in time? Drop a comment below , I am genuinely curious how many CI pipelines pulled the bad version and what the incident response looked like. And if you have a workflow change that keeps your supply chain cleaner, share it. Everyone here builds with the same ecosystem and we all benefit from each other's hard lessons.
Author Parth Sharma
Full-Stack Developer, Freelancer, & Founder. Obsessed with crafting pixel-perfect, high-performance web experiences that feel alive.
Discussion0
Join the conversation
Sign in to leave a comment, like, or reply.
No comments yet. Start the discussion!