On March 31, 2026, the npm package axios — one of the most widely used HTTP client libraries in the JavaScript ecosystem — was compromised in a supply chain attack. This is the second major supply chain incident to hit the open-source community in just one week, following the LiteLLM compromise on March 24.
Here’s what happened, how Comet responded, and what you should do to protect your systems.
What Happened
A compromised version of axios (1.14.1) was published to npm containing a new malicious dependency: plain-crypto-js@4.2.1. This package did not exist before the attack — it was created minutes before the compromised axios version was published and has no corresponding source code in any public repository.
Because axios uses semver versioning and most projects depend on it with caret ranges (e.g., ^1.13.4), any project that ran npm install without a lockfile during the attack window would have automatically pulled in the compromised version.
Impact Scale
Axios is one of npm’s most depended-on packages, with over 60 million weekly downloads. It’s used by countless frontend applications, backend services, CLI tools, and CI/CD pipelines across the industry.
The Payload: A Full Remote Access Trojan
Unlike simpler supply chain attacks that grab environment variables, this attack deployed a persistent remote access trojan (RAT) with full command-and-control capabilities.
How the attack chain works:
Stage 1 — Delivery: The malicious plain-crypto-js package runs a postinstall hook (setup.js) that uses two-layer obfuscation — reversed Base64 encoding combined with an XOR cipher (key: OrDeR_7077) — to evade static analysis and security scanners.
Stage 2 — Platform-specific backdoor installation: The dropper detects the operating system and deploys a tailored backdoor:
- macOS: Downloads a Mach-O binary to
/Library/Caches/com.apple.act.mond, disguised as an Apple system daemon. It launches via AppleScript to evade process-tree detection. - Windows: Copies PowerShell to
%PROGRAMDATA%\wt.exe, downloads a.ps1payload via VBScript, and executes it hidden from the user. - Linux: Downloads a Python script to
/tmp/ld.pyand runs it in the background vianohup.
Stage 3 — Remote access trojan: Once installed, the backdoor beacons to a command-and-control server (sfrclak[.]com:8000) every 60 seconds via HTTP POST, using a fake Internet Explorer user agent string. It collects system fingerprinting data including hostname, username, OS version, timezone, CPU type, running processes, and directory listings.
The RAT supports four commands from the attacker:
peinject— deploy additional binary payloads (further malware)runscript— execute arbitrary shell commands or AppleScriptrundir— enumerate the filesystem with metadatakill— terminate the RAT process
This means the attacker doesn’t just steal your data once — they maintain persistent access to execute anything on your machine at any time.
Stage 4 — Anti-forensics: After execution, the payload self-deletes the dropper script and overwrites its own package.json to remove traces of the malicious code, making post-incident detection significantly harder.
How Comet Responded
Having just dealt with the LiteLLM supply chain attack one week earlier, our team was already on high alert. When the axios compromise was flagged by the community on the morning of March 31, we had a response running within minutes.
Our response included:
- Immediate repository audit: A full scan of all JavaScript and TypeScript repositories across the organization — every
package.json, every lockfile (package-lock.json,yarn.lock,pnpm-lock.yaml), and everynode_modulesdirectory was checked for the maliciousplain-crypto-jspackage and for any resolved axios version matching 1.14.x. - CI/CD build audit: We reviewed three days of GitHub Actions workflow runs across all active repositories, checking for any builds that may have pulled the compromised version during the attack window.
- Developer machine scans: We built and open-sourced a scanner script that checks all lockfiles, node_modules, and global installs for any trace of the compromised package. We distributed it across the entire engineering team within minutes. You can use it too — just run:
bash
bash <(curl -sL https://gist.githubusercontent.com/Nimrod007/13ad665e473221b4d5da7a85f26c79c5/raw/check_axios_compromise.sh)
The script scans your machine and reports CLEAN or COMPROMISED in seconds. Feel free to copy it and share it across your organization.
Production verification: Confirmed all production and single-tenant SaaS environments were unaffected — these are containerized with no live npm install operations.
Result: No Comet systems were compromised. All lockfiles pinned axios to safe versions (1.13.x and earlier), and no build or developer machine showed any trace of the malicious package.
Lessons from Two Attacks in One Week
The LiteLLM and axios attacks share a common theme: they exploit the trust developers place in package managers to deliver safe code. But they also highlight what works as a defense:
1. Lockfiles saved us — twice. In both incidents, committed lockfiles (package-lock.json, poetry.lock, uv.lock) prevented automatic resolution to compromised versions. This is the single most effective defense against supply chain attacks.
2. Fast detection matters. Our engineering team flagged the axios compromise within hours of publication. Having been through the LiteLLM incident just days earlier, the team was already sensitized to supply chain risks and responded immediately.
3. Scanning infrastructure pays off. The scanner scripts and audit processes we built for the LiteLLM response were adapted and redeployed within minutes for the axios incident. Investing in incident response tooling compounds over time.
How to Check If You’re Affected
Check your lockfiles
Search all your JavaScript/TypeScript projects for the malicious package:
bash
# Search for the malicious dependency in lockfiles
grep -r "plain-crypto-js" ~/path/to/your/projects/
# Check if any lockfile resolves axios to 1.14.x
grep "axios/-/axios-1.14" ~/path/to/your/projects/**/package-lock.json
If either command returns results, treat the system as potentially compromised.
Check your node_modules
bash
# Check for the malicious package installed anywhere
find ~ -maxdepth 6 -name "node_modules" -type d -exec test -d "{}/plain-crypto-js" \; -print
If plain-crypto-js appears in any node_modules, that project has been compromised.
Mitigation Steps
If you are NOT affected:
- Verify your lockfiles are committed to version control
- Consider pinning critical dependencies to exact versions (e.g.,
"axios": "1.13.4"instead of"^1.13.4") - Use
npm ciinstead ofnpm installin CI/CD pipelines for deterministic builds - Enable dependency scanning tools like Socket.dev,
npm audit, or GitHub Dependabot
If you ARE affected:
1. Stop immediately — do not run any npm, yarn, or pnpm commands
2. Delete the affected node_modules directory and lockfile
3. Check for persistence — look for files at the known dropper locations:
- macOS:
/Library/Caches/com.apple.act.mond - Windows:
%PROGRAMDATA%\wt.exe - Linux:
/tmp/ld.py
4. Rotate all credentials — API keys, tokens, SSH keys, cloud credentials, and any secrets that were present on the compromised system
5. Reinstall from clean lockfile — use a known-good lockfile and run npm ci
6. Monitor for unauthorized access — check cloud provider audit logs for suspicious activity
Current Status
The compromised axios@1.14.1 has been permanently removed from npm. Running npm install axios now resolves to safe versions. The malicious plain-crypto-js@4.2.1 has also been removed.
Stay Vigilant
Two major supply chain attacks in one week is a stark reminder that the open-source ecosystem remains a high-value target. The defenses that protected Comet — committed lockfiles, fast incident response, and a culture of security awareness — are available to every engineering team. The question is whether they’re in place before the next attack hits.
—
For more details on the LiteLLM incident from last week, see our previous post: LiteLLM Supply Chain Attack: What Happened, Who’s Affected, and What You Should Do Right Now.
