On March 31, 2026, the software development and Web3 communities were hit by one of the most severe supply chain attacks in recent history. Axios, an incredibly popular JavaScript HTTP client with an estimated 100 million to over 300 million weekly downloads, was compromised. Threat actors injected a malicious dependency that delivered a cross-platform Remote Access Trojan (RAT) directly to developer workstations, CI/CD runners, and enterprise servers.
When the attack first happened, Axios maintainers were unable to regain control of the project. In a public GitHub issue, a collaborator stated they could not revoke access from the account responsible for the malicious publish, noting that the attacker’s permissions exceed their own.
This incident stands out not just for its massive blast radius, but for the sophisticated techniques the attackers used to bypass modern CI/CD safeguards, evade forensic detection, and exploit modern AI-assisted development habits.
- Account Hijack and Bypassing SLSA Provenance
The attack was not the result of a vulnerability in the Axios source code. Instead, it was a direct release-path hijacking. The attacker compromised the npm account of Jason Saayman, the primary maintainer of the Axios project, and changed the associated email to an attacker-controlled ProtonMail address (ifstap@proton.me).
Using these compromised credentials, the attacker manually published two malicious versions: axios@1.14.1 and axios@0.30.4. This manual publication via the npm CLI bypassed the project's standard GitHub Actions continuous integration pipeline. Consequently, these malicious versions lacked OIDC Trusted Publisher cryptographic SLSA provenance, and had no corresponding source code commits or tags on the official Axios GitHub repository.
- The "Phantom Dependency" Injection
To avoid drawing attention through large code modifications, the attacker did not alter a single line of the actual Axios JavaScript source. Instead, they made a surgical edit to the package.json file, adding a new dependency: plain-crypto-js@^4.2.1.
This is known as a "phantom dependency." The plain-crypto-js package was never imported or required anywhere in the Axios execution path. Its sole purpose was to exist in the dependency tree so that npm would automatically execute its postinstall lifecycle script ("postinstall": "node setup.js") during routine dependency resolution.
To build credibility and evade zero-history scanners, the attacker (using the account nrwise@proton.me) first published a clean decoy version of the package (4.2.0) containing legitimate cryptography library code. Just minutes before pushing the poisoned Axios releases, they published the malicious 4.2.1 update.
- Obfuscation and Platform-Specific RATs
When a developer or build server ran npm install, the setup.js dropper was triggered. This script utilized a custom two-layer obfuscation scheme designed to defeat static analysis. Strings were reversed, base64-encoded, and padded with underscores, then decrypted using a position-dependent XOR cipher derived from the key "OrDeR_7077" and XORed again with the constant 333.
Once deobfuscated, the dropper detected the host operating system (os.platform()) and contacted the Command and Control (C2) server at http://sfrclak.com:8000/6202033 (IP: 142.11.206.73). To blend in with legitimate traffic, the malware spoofed HTTP POST bodies to look like npm registry requests, using strings such as packages.npm.org/product0.
The C2 server dynamically delivered specialized second-stage payloads:
macOS (product0): An AppleScript fetched a Mach-O universal binary RAT written in C++. It was saved to /Library/Caches/com.apple.act.mond—deliberately mimicking Apple's reverse-DNS daemon naming conventions to blend into routine system background processes—and executed via /bin/zsh.
Windows (product1): The dropper utilized an Endpoint Detection and Response (EDR) evasion tactic by copying the system's PowerShell binary to %PROGRAMDATA%\wt.exe to disguise it as Windows Terminal. A hidden VBScript then silently executed a .ps1 PowerShell RAT reflectively.
Linux (product2): The dropper fetched a Python script to /tmp/ld.py and ran it as a detached background process using nohup python3. This allowed the malware process to orphan itself to PID 1, surviving long after the initial npm install command had terminated.
- Anti-Forensics and the "Vibe Coding" Threat
After the malware was successfully deployed, the setup.js script immediately initiated a self-destruct sequence. It deleted its own script file, deleted the infected package.json, and restored a pre-staged clean decoy (package.md) in its place. As a result, any developer casually inspecting the node_modules/plain-crypto-js directory post-infection would see a clean cryptography library with no postinstall hook, effectively neutralizing shallow forensic audits.
The rapid propagation of this malware was severely exacerbated by the modern AI "vibe coding" trend. Developers utilizing AI agents (such as Claude) to scaffold applications frequently execute npm install commands without manually auditing package.json diffs or lockfiles. Because developers implicitly trusted the AI's output, the malware cascaded into downstream AI tooling within hours, compromising packages like @shadanai/openclaw and @qqbrowser/openclaw-qbot.
Immediate Remediation Plan
If you or your CI/CD pipelines installed axios@1.14.1 or axios@0.30.4, you must assume total host compromise. The payload has full capabilities to exfiltrate SSH keys, cloud CLI credentials, and crypto-wallet private keys. Remediation requires a comprehensive response:
Pin Safe Versions: Explicitly lock Axios to 1.14.0 or 0.30.3 in your package.json and lockfiles.
Hunt for Artifacts: Check for the presence of the node_modules/plain-crypto-js directory, /tmp/ld.py, %PROGRAMDATA%\wt.exe, or /Library/Caches/com.apple.act.mond.
Rebuild, Don't Clean: If artifacts are found, do not attempt to clean the system in place. Rebuild affected developer machines and persistent CI runners from known-good base images.
Rotate All Secrets: Rotate any SSH keys, cloud credentials, npm tokens, and .env variables that were present on the host during the npm install window.
Enforce Safe Installs: Update your CI/CD pipelines to default to npm ci --ignore-scripts to categorically prevent dependency lifecycle scripts from executing without explicit authorization during automated builds.


Top comments (0)