On March 31, 2026, StepSecurity identified two malicious versions of axios, one of the most widely used JavaScript HTTP client libraries, published to npm via a compromised lead maintainer account: [email protected] and [email protected]. Both versions inject a rogue dependency, [email protected], that executes a cross-platform RAT dropper on npm install. The attack bypassed axios's GitHub Actions CI/CD pipeline entirely; the attacker hijacked the maintainer account, changed the email to an anonymous ProtonMail address, and published manually via the npm CLI. Any developer or CI system that ran npm install with these versions should assume compromise.
What Happened
The attack was pre-staged across roughly 18 hours with deliberate operational security:
- 2026-03-30 05:57 UTC:
[email protected]published by[email protected]. A clean decoy containing a full copy of legitimatecrypto-jssource with no malicious code. Purpose: establish npm publishing history so the package does not trigger "zero-history account" security scanner alerts. - 2026-03-30 23:59 UTC:
[email protected]published. Malicious postinstall hook added:"postinstall": "node setup.js"with obfuscated dropper code. - 2026-03-31 00:21 UTC:
[email protected]published via the compromisedjasonsaaymanmaintainer account. The account email had been changed to an anonymous ProtonMail address, bypassing GitHub-linked publish verification. - Shortly after:
[email protected]published by the same account. Both versions list[email protected]as a new dependency that was never present in any prior axios release.
Neither poisoned version contains malicious code inside axios itself. The malware is entirely inside [email protected], which is never imported by axios's source code; it exists solely to execute at install time.
What Was Taken
The dropper contacts a live C2 server (sfrclak.com / 142.11.206.73) and delivers platform-specific second-stage payloads:
- macOS:
/Library/Caches/com.apple.act.mond - Windows:
%PROGRAMDATA%\wt.exe - Linux:
/tmp/ld.py
After execution, the malware deletes itself and replaces its own package.json with a clean decoy. A developer inspecting node_modules after the fact will find no visible evidence of the malicious dependency.
The second-stage RAT payloads provide persistent remote access. Full capability analysis is ongoing. At minimum, assume: credential theft, environment variable exfiltration (including CI secrets, API keys, tokens), and potential lateral movement from any compromised developer workstation or CI runner.
Why It Matters
axios has 50+ million weekly npm downloads. This is not a niche package. It is a direct or transitive dependency in a substantial fraction of Node.js applications, build pipelines, and CI environments globally.
The attack model defeats standard CI security controls. By publishing via the npm CLI with compromised credentials rather than through GitHub Actions, the attacker bypassed the project's automated publishing safeguards. Package signing alone does not help here; the package was legitimately signed by the real maintainer's (compromised) account.
The pre-staging is sophisticated. Publishing a clean decoy version of plain-crypto-js 18 hours before the attack to establish publishing history is a deliberate counter-detection step. This is not opportunistic; it mirrors the TeamPCP methodology used against Trivy and the Telnyx SDK earlier this week.
Self-destruction on execution. The malware actively removes forensic evidence after running. Post-infection inspection of node_modules will not reveal compromise. The only reliable detection signals are network-level (C2 connections to sfrclak.com) and filesystem-level (checking for the dropped files).
CI runners are the primary blast radius. Any CI/CD system that runs npm install without a lockfile pinning or integrity check, including GitHub Actions, GitLab CI, Jenkins, CircleCI, may have executed the dropper with elevated permissions and access to secrets injected as environment variables.
The Attack Technique
- Account takeover: Lead maintainer
jasonsaaymanaccount compromised; email swapped to[email protected]to sever GitHub Actions publish verification - Dependency injection:
[email protected]listed as a new runtime dependency in[email protected]and0.30.4 - Postinstall execution: npm runs
node setup.jsautomatically on package install; no user interaction required - Obfuscated dropper:
setup.jsidentifies the host OS, contacts C2, pulls and executes platform-specific second-stage payload - Self-erasure: Malware deletes
setup.jsand writes a cleanpackage.jsonover itself to evade post-infection detection
IOCs
| Type | Indicator |
|---|---|
| Malicious packages | [email protected], [email protected], [email protected] |
| C2 domain | sfrclak.com |
| C2 IP | 142.11.206.73 |
| macOS file | /Library/Caches/com.apple.act.mond |
| Windows file | %PROGRAMDATA%\wt.exe |
| Linux file | /tmp/ld.py |
What Organizations Should Do
-
Scan all lockfiles immediately. Run
grep -r "1.14.1\|0.30.4" package-lock.json yarn.lockacross every repository, including transitive dependencies. Check forplain-crypto-jsanywhere in your dependency trees. -
If found, assume full compromise. Rotate all secrets, API keys, tokens, and credentials accessible from affected machines or CI environments. This includes environment variables injected into CI runners, SSH keys, cloud credentials, and npm tokens.
-
Block C2 at the network perimeter. Immediately block
sfrclak.comand142.11.206.73at your egress firewall or DNS resolver. Check historical DNS and network logs for connections to these indicators from dev machines and CI systems. -
Check for dropped files on all developer machines and CI runners. Look for
/Library/Caches/com.apple.act.mond(macOS),%PROGRAMDATA%\wt.exe(Windows),/tmp/ld.py(Linux). Presence confirms execution. -
Pin to safe versions.
[email protected](1.x branch) or[email protected](0.x branch) are clean. Update lockfiles and commit. -
Enforce lockfile integrity in CI. Use
npm ci(notnpm install) in all CI pipelines; it installs from the lockfile and fails if the lockfile doesn't match. Enablenpm auditas a gate. Consider Artifact Transparency tools (Socket, StepSecurity Harden-Runner) to detect new transitive dependencies at publish time.