Table of contents
On March 31, 2026, attackers compromised the primary maintainer account of the axios npm package and published two malicious versions that silently installed a cross-platform Remote Access Trojan (RAT) on macOS, Windows, and Linux systems. Axios is one of the most widely used JavaScript libraries, with roughly 100 million weekly downloads and over 174,000 dependent packages. The poisoned versions were live for under three hours, but any project that ran npm install during that window was silently backdoored. This is not a vulnerability in the axios codebase itself, so a traditional CVE is unlikely to be assigned. Tracking is through npm security advisories and GitHub Security Advisories (GHSA).
Quick Overview
| Attribute | Details |
|---|---|
| CVE | N/A (supply chain compromise, not a code vulnerability; tracked via npm/GHSA advisories) |
| Severity | Critical (supply chain RCE with no user interaction) |
| Type | Supply chain compromise (maintainer account takeover) |
| CWE | CWE-506 (Embedded Malicious Code) |
| Affected Packages | axios, plain-crypto-js, @shadanai/openclaw, @qqbrowser/openclaw-qbot |
| Compromised Versions | axios@1.14.1, axios@0.30.4, plain-crypto-js@4.2.1 |
| Safe Versions | axios@1.14.0 (1.x), axios@0.30.3 (0.x) |
| Attack Vector | Network (npm install triggers payload automatically) |
| Authentication Required | None |
| User Interaction | None (postinstall hook runs automatically) |
| Active Exploitation | Yes, confirmed |
| CISA KEV | No |
| Fix Available | Yes, revert to axios@1.14.0 or axios@0.30.3 |
What is Axios?
Axios is a promise-based HTTP client for JavaScript that works in both Node.js and the browser. If you’ve written JavaScript in the last decade, you’ve almost certainly used it or depended on something that does. It sits in the dependency tree of over 174,000 npm packages, which makes it one of those foundational libraries where a compromise doesn’t just affect direct users. It cascades downstream into countless applications, CI/CD pipelines, and production environments.
| Timestamp (UTC) | Details |
|---|---|
| Mar 30, 05:57 | plain-crypto-js@4.2.0 published by npm user nrwise (nrwise@proton.me), a clean copy of crypto-js staged to build publishing history |
| Mar 30, 23:59 | plain-crypto-js@4.2.1 published by the same account with malicious postinstall hook and obfuscated dropper added |
| Mar 31, 00:05 | Socket’s automated detection flags plain-crypto-js@4.2.1 within 6 minutes of publication |
| Mar 31, 00:21 | axios@1.14.1 published by the compromised jasonsaayman npm account (email changed to ifstap@proton.me) |
| Mar 31, 01:00 | axios@0.30.4 published by the same compromised account, targeting the legacy 0.x branch |
| Mar 31, ~03:15 | npm unpublishes both malicious axios versions; latest dist-tag reverts to 1.14.0 |
| Mar 31, 04:26 | npm publishes security-holder stub plain-crypto-js@0.0.1-security.0, formally neutralizing the malicious package |
Socket co-founder Feross Aboukhadijeh issued the first public alert on X/Twitter. StepSecurity researcher Ashish Kurmi opened GitHub Issue #10604 to coordinate community response and submitted a vulnerability report, though a traditional CVE is unlikely since this is a supply chain compromise rather than a code vulnerability.
Technical Analysis
How the account was compromised
The attack started with a takeover of the jasonsaayman npm account, the primary maintainer of axios. The attacker changed the account’s registered email to a ProtonMail address they controlled (ifstap@proton.me) and used the npm CLI to publish the poisoned packages directly.
This is significant because legitimate axios releases use npm’s Trusted Publishing mechanism (a system where packages are published through GitHub Actions with cryptographic OIDC tokens that tie each release to a specific CI workflow, making it impossible to publish without a corresponding code change). The malicious versions were published manually, completely bypassing this. The likely entry point was a long-lived classic npm access token, which can sidestep 2FA requirements entirely, unlike the ephemeral OIDC tokens used by Trusted Publishing.
The forensic signal is clear: the legitimate axios@1.14.0 shows GitHub Actions as the publisher with a trustedPublisher OIDC attestation, while axios@1.14.1 shows jasonsaayman as the publisher with a ProtonMail address and no provenance data at all. No corresponding commit, tag, or release exists in the axios GitHub repository.
The phantom dependency trick
The attacker didn’t modify any of axios’ JavaScript source files. The only change was in package.json: a new runtime dependency on plain-crypto-js@^4.2.1 was added, and the version number was bumped. A search of all 86 files in axios@1.14.1 confirms that plain-crypto-js is never imported or required anywhere in the codebase. It exists purely as a “phantom dependency” whose postinstall hook (a script that npm automatically runs after installing a package) triggers the malicious payload.
The attacker pre-staged this carefully. Roughly 18 hours before the axios compromise, a clean version of plain-crypto-js@4.2.0 was published by the npm user nrwise (nrwise@proton.me). This version was an exact copy of the legitimate crypto-js library with no malicious code, designed to build publishing history and dodge detection heuristics that flag brand-new packages. The malicious 4.2.1 followed a day later, adding an obfuscated dropper script (setup.js) and a postinstall hook to execute it.
Inside the dropper
The setup.js dropper (4,209 bytes) uses a two-layer encoding scheme to hide its intent. All sensitive strings are stored in an encoded array and decoded through two chained functions. The inner function applies an XOR cipher (a reversible bitwise operation commonly used in simple obfuscation) with the key “OrDeR_7077“. Because JavaScript’s Number() coerces alphabetic characters to NaN (which becomes 0 in bitwise operations), the effective key reduces to the byte sequence [0,0,0,0,0,0,7,0,7,7]. Each character is decoded as charCode XOR key[(7 * r * r) % 10] XOR 333. The outer function reverses the string, swaps underscores for equals signs, base64-decodes, and then feeds the result through the XOR layer.
Once decoded, the dropper reveals its operational structure: it imports child_process, os, and fs, identifies the host platform, and reaches out to the C2 (Command and Control, the attacker-operated server that issues instructions) server at http://sfrclak.com:8000/6202033 to fetch a platform-specific RAT payload.
Platform-specific payloads
The attack deployed three distinct payloads depending on the operating system:
macOS: The dropper writes an AppleScript file to the system’s temp directory and runs it silently via osascript. The script contacts the C2 server, downloads a compiled C++ RAT binary, and saves it to /Library/Caches/com.apple.act.mond, a path deliberately chosen to mimic Apple’s reverse-DNS naming convention for system daemons. The binary is made executable with chmod 770 and launched via /bin/zsh. According to StepSecurity’s analysis, the RAT beacons to the C2 server every 60 seconds, supports shell command execution, filesystem enumeration, and self-termination.
Windows: The dropper locates the PowerShell binary, copies it to %PROGRAMDATA%\wt.exe (disguised as Windows Terminal), writes a VBScript to the temp directory, and executes it via cscript. The VBScript launches a hidden cmd.exe that downloads a PowerShell-based RAT script from the C2, saves it to %TEMP%\6202033.ps1, and runs it with -ExecutionPolicy Bypass -WindowStyle Hidden.
Linux: A shell command downloads a Python RAT script to /tmp/ld.py and executes it detached via nohup python3. StepSecurity’s runtime analysis confirmed the Python process is deliberately orphaned to PID 1 (meaning its parent process ID is set to the init system), which helps it evade process-tree attribution and persist beyond the npm install session.
All three payloads use POST bodies formatted as packages.npm.org/product0, product1, or product2 when communicating with the C2 server. This formatting is deliberate camouflage designed to make outbound traffic look like legitimate npm registry communication in network monitoring tools.
Anti-forensic evidence destruction
After launching the payload, the dropper cleans up after itself in three steps: it deletes setup.js, deletes the malicious package.json (which contains the incriminating postinstall hook), and then renames a pre-staged clean manifest file (package.md) to package.json. The result is that anyone inspecting node_modules/plain-crypto-js/ after infection would find a perfectly clean package.json with no scripts section and no trace of the dropper. npm audit will detect nothing. StepSecurity’s Harden-Runner captured this swap happening: the malicious manifest was written, and the clean replacement appeared 36 seconds later.
Attack Flow
- Attacker compromises the
jasonsaaymannpm account (likely via a stolen long-lived access token) - Attacker pre-stages
plain-crypto-js@4.2.0(clean) then4.2.1(malicious) under a throwaway npm account - Attacker publishes
axios@1.14.1andaxios@0.30.4withplain-crypto-jsinjected as a dependency - Any
npm installautomatically resolves the new axios version (via caret ranges) and runsplain-crypto-js‘spostinstallhook - The
postinstallhook executessetup.js, which decodes and runs the platform-specific dropper - The dropper contacts the C2 server, downloads a RAT, and installs persistent access within 1.1 seconds of
npm installcompleting - The dropper destroys all evidence of itself, leaving a clean
package.jsonin its place
Affected Versions
| Package | Compromised Version | Safe Version | Notes |
|---|---|---|---|
| axios | 1.14.1 | 1.14.0 | 1.x branch, published via compromised maintainer account |
| axios | 0.30.0 | 0.30.0 | Legacy 0.x branch, same attack |
| plain-crypto-js | 4.2.1 | N/A | Malicious dependency, now under npm security hold |
| @shadanai/openclaw | 2026.3.28-2 through 2026.3.31-2 | N/A | Additional distribution vector identified by Socket |
| @qqbrowser/openclaw-qbot | 0.0.130 | N/A | Ships vendored malicious axios in node_modules/ |
All compromised versions have been unpublished from npm. The latest dist-tag for axios currently points to 1.14.0.
Threat Status
Exploitation Activity: Confirmed active. The malicious versions were live on npm for approximately 2-3 hours. StepSecurity confirmed via Harden-Runner that the first C2 connection fires 1.1 seconds after npm install completes. The compromise was independently detected in CI runs for the backstage repository, one of the most widely used developer portal frameworks, confirming real-world execution in production pipelines.
PoC Availability: The malicious code itself was captured and analyzed by Socket, StepSecurity, and SafeDep before npm removed the packages. Detailed technical teardowns are publicly available. The C2 server domain (sfrclak.com) was still resolving at the time of initial reporting.
Attribution: No formal attribution to any known threat group has been published. Socket explicitly stated they found no evidence linking this to the recently reported TeamPCP campaigns. The security community has noted the absence of cryptocurrency miners or ransomware in the payload, pointing instead to persistent C2 beaconing, system reconnaissance, and targeting of .ssh and .aws directories. This behavior pattern is more consistent with an APT (Advanced Persistent Threat) actor focused on intelligence gathering than financially motivated crime. However, this remains speculative.
Why This Matters
The immediate blast radius is enormous. Any project using a caret range dependency on axios (npm’s default version syntax, where ^1.14.0 means “accept any compatible version up to the next major release”) that ran npm install during the roughly three-hour window would have automatically pulled the compromised version. Given axios’ 100 million weekly downloads and 174,000+ dependents, even a short exposure window translates to significant potential impact. CI/CD pipelines running on schedule, developers starting their morning, automated deployments, anything that touched npm install during those hours is potentially compromised.
What makes this attack particularly concerning for the broader ecosystem is that axios had already adopted npm’s Trusted Publishing mechanism. In theory, this should prevent exactly this kind of attack by tying releases to verifiable CI workflows. But the maintainer’s account also retained a classic long-lived npm token, and the attacker used that token to bypass every provenance control. This is a structural lesson: Trusted Publishing only works if it’s the sole publishing path. As long as legacy tokens coexist with modern provenance systems, they represent a backdoor around those protections.

The operational sophistication here is also worth noting. This wasn’t a smash-and-grab. The attacker staged a clean decoy package 18 hours in advance, hit both the current and legacy release branches within 39 minutes of each other, built platform-specific RAT payloads for all three major operating systems, disguised C2 traffic as npm registry calls, and destroyed all forensic evidence within 36 seconds of execution. That level of planning and execution suggests a well-resourced and experienced adversary.
Remediation
Primary Action
Pin axios to a known-safe version immediately: npm install axios@1.14.0 (for the 1.x branch) or npm install axios@0.30.3 (for the legacy 0.x branch).
Version-Specific Instructions
| Scenario | Action |
|---|---|
| Using axios 1.x with caret range | Run npm install axios@1.14.0 and verify package-lock.json shows 1.14.0 |
| Using axios 0.x with caret range | Run npm install axios@0.30.3 and verify lockfile |
| CI/CD pipelines | Audit workflow run logs during the exposure window (approx. 00:21-03:15 UTC, March 31). Rotate all injected secrets for any affected runs |
| Confirmed compromise (RAT artifacts found) | Do not attempt to clean in place. Rebuild the system from a known-good state |
Interim Mitigations
If you cannot immediately verify and rebuild affected systems:
- Block C2 traffic by adding
sfrclak.comand142.11.206.73to firewall blocklists and DNS sinkholes - Run
npm install --ignore-scriptsas a standing policy in CI/CD environments to prevent postinstall hooks from executing automatically - Rotate all credentials accessible from potentially affected systems: npm tokens, AWS keys, SSH private keys, CI/CD secrets, database passwords, and
.envfile contents
Post-Compromise Considerations
If you find any of the RAT artifacts listed below, or if your lockfile confirms installation of axios@1.14.1 or axios@0.30.4, treat the system as fully compromised:
- Rebuild from a known-good image or backup
- Rotate every secret and credential that was accessible on the system
- Review authentication logs for unauthorized access originating from the compromised host
- Check for lateral movement, particularly in cloud environments where IAM credentials or SSH keys may have been exfiltrated
Detection Guidance
Package hashes (for detection and verification)
| Package | SHA256 |
|---|---|
| axios@1.14.1 | 5bb67e88846096f1f8d42a0f0350c9c46260591567612ff9af46f98d1b7571cd |
| axios@0.30.4 | 59336a964f110c25c112bcc5adca7090296b54ab33fa95c0744b94f8a0d80c0f |
| plain-crypto-js@4.2.1 | setup.js: e10b1fa84f1d6481625f741b69892780140d4e0e7769e7491e5f4d894c2e0e09 |
Host-level indicators
| Platform | Path | Description |
|---|---|---|
| macOS | /Library/Caches/com.apple.act.mond | C++ RAT binary (persistent) |
| Windows | %PROGRAMDATA%\wt.exe | Copied PowerShell binary disguised as Windows Terminal |
| Windows | %TEMP%\6202033.ps1 | PowerShell RAT script (may self-delete) |
| Windows | %TEMP%\6202033.vbs | VBScript dropper (may self-delete) |
| Linux | /tmp/ld.py | Python RAT script |
| All platforms | node_modules/plain-crypto-js/ | Presence of this directory indicates the dropper ran |
Detection Commands

How Can Orca Help?
Orca enables customers to identify cloud workloads and container images running compromised axios versions, understand exposure context (including internet accessibility, attack path reachability, and asset criticality), and prioritize remediation based on real risk. Orca’s News Item view highlights affected assets directly, helping security teams focus on the most critical systems first.

