Axios npm Compromise: Lazarus Group Deploys Cross-Platform RAT
On March 31, 2026, the axios npm package, with over 50 million weekly downloads, was compromised via a maintainer account hijack. Two malicious versions (1.14.1 and 0.30.4) were published between 00:21 and 03:29 UTC, injecting a dependency on plain-crypto-js, an obfuscated postinstall dropper that delivers a cross-platform remote access trojan targeting Windows, macOS, and Linux.
The macOS payload is classified as NukeSped by four antivirus engines. NukeSped is a backdoor family attributed to Lazarus Group (DPRK/APT38), the same threat actor behind the 2022 Ronin Bridge theft ($625M), the 2024 WazirX exchange hack ($230M), and the February 2025 Bybit theft ($1.4B). This marks Lazarus's first confirmed compromise of a top-100 npm package.
axios sits in the dependency tree of an estimated 12 million GitHub repositories and is a transitive dependency of most Node.js web frameworks. A compromised version propagates through CI/CD pipelines, automated dependency updates (Dependabot, Renovate), and developer workstations within minutes of publication.
The compromise was first reported by the community around 02:00 UTC and the malicious versions were unpublished by 03:29 UTC. StepSecurity, Socket, Snyk, and Semgrep published early analyses confirming the scope, while N3mes1s released a detailed reverse engineering of the dropper with YARA, Sigma, and Suricata rules.
This post builds on that collective work with a focus on the full attack chain from npm registry to RAT deployment, the XOR obfuscation scheme used in the dropper, all three platform-specific payloads, the C2 infrastructure, and the 33 maldet signatures we published for detection.
Critical: Check your npm lockfiles now
If your package-lock.json or yarn.lock references axios@1.14.1, axios@0.30.4, or plain-crypto-js, your system executed the dropper during npm install. Safe versions: 1.14.0 and 0.30.3.
The Attack
The attacker compromised the npm account of jasonsaayman, a legitimate axios maintainer. The compromise vector is consistent with credential theft via social engineering or infostealer malware, a technique Lazarus has refined across previous DeceptiveDevelopment campaigns targeting open-source maintainers. A second account, nrwise (email: nrwise@proton.me), was created to publish the malicious dependency. The attack targeted two version branches simultaneously to maximize coverage across pinned and floating dependency ranges.
| TIME (UTC) | EVENT |
|---|---|
| Mar 30 16:03 | sfrclak.com registered (C2 domain) |
| Mar 31 00:21 | axios@1.14.1 published (compromised) |
| Mar 31 00:21 | axios@0.30.4 published (compromised) |
| Mar 31 00:21 | plain-crypto-js@4.2.1 published (dropper) |
| Mar 31 ~02:00 | Community reports begin (GitHub #10604) |
| Mar 31 03:29 | Malicious versions unpublished from npm |
The three-hour window between publication and removal is consistent with Lazarus Group's previous npm campaigns (e.g., the 2023 crypto-dashboard-helper incident), where a short burst window captures installs from CI/CD pipelines running on schedules, automated dependency updates, and developers working across time zones. Publishing to both the 1.x and 0.x branches was deliberate: projects pinning to legacy 0.x releases (common in enterprise codebases with conservative upgrade policies) were hit alongside those tracking the latest.
Attack Chain
The kill chain flows from npm registry to platform-specific RAT deployment in four stages. The dropper uses XOR obfuscation with a deterministic key to evade static analysis, then branches by OS to download the appropriate payload from the C2 server.
The Dropper
The plain-crypto-js package contains a single file, setup.js, registered as a postinstall script. npm executes postinstall hooks automatically after npm install with no user interaction required. npm does not sandbox lifecycle scripts; they execute with the installing user's full permissions.
The payload is obfuscated with a deterministic XOR cipher. Every character is transformed through a formula that uses the position index to select a key byte, making the output deterministic (the same input always produces the same ciphertext):
// Deobfuscation formula (from setup.js)
const key = "OrDeR_7077";
const constant = 333;
function decode(encoded, r) {
return String.fromCharCode(
encoded.charCodeAt(0) ^ key.charCodeAt((7 * r * r) % 10) ^ constant
);
}Because the XOR key (OrDeR_7077) and constant (333) are embedded as string literals, the obfuscated output has stable byte sequences suitable for hex pattern matching. The decoded payload performs OS detection and fetches the platform-specific RAT from one of three C2 endpoints.
| PLATFORM | C2 ENDPOINT | PAYLOAD |
|---|---|---|
| macOS | /packages.npm.org/product0 | Universal Mach-O binary (NukeSped) |
| Windows | /packages.npm.org/product1 | system.bat → PS RAT via wt.exe |
| Linux | /packages.npm.org/product2 | ld.py Python RAT |
The C2 URI path /packages.npm.org/ is deliberately crafted to resemble legitimate npm infrastructure in proxy logs, blending with normal package resolution traffic.
Platform Payloads
Windows: Staged RAT via Renamed PowerShell
The Windows payload uses a two-stage approach. Stage 1 (system.bat) drops to C:\ProgramData\, copies powershell.exe to wt.exe (LOLBin evasion), then downloads the PowerShell RAT as Stage 2.
Persistence is achieved via registry key at HKCU\Software\Microsoft\Windows\CurrentVersion\Run\MicrosoftUpdate, with campaign artifacts using the ID 6202033 as a naming convention across temporary VBS and PS1 files.
macOS: NukeSped Universal BinaryAPT38
The macOS payload is a fat Mach-O binary containing both x86_64 and ARM64 slices, classified as NukeSped by four antivirus engines. Build metadata reveals the Xcode project name macWebT, developer path Jain_DEV, and a .NET embedded class Extension.SubRoutine.
Persistence is achieved by masquerading as a macOS system daemon at /Library/Caches/com.apple.act.mond, a deliberately crafted name within Apple's namespace designed to blend with legitimate LaunchDaemon entries.
Linux: Python RAT
The Linux payload is a Python script dropped to /tmp/ld.py that provides full remote access via subprocess execution. It beacons to the C2 with JSON payloads containing three message types: FirstInfo (initial host fingerprint), BaseInfo (system metadata), and CmdResult (command output). All beacons are base64-encoded in HTTP POST bodies, using a spoofed IE8 User-Agent string.
Server-side priority
Linux servers running CI/CD pipelines, build farms, and Node.js applications are the highest-risk targets. The dropper executes during npm install in any context: development, CI, staging, or production.
C2 Infrastructure
Both C2 domains were registered less than 15 hours before the attack, hosted on a single IP address at Hostwinds (Seattle, WA). The server uses cleartext HTTP on port 8000 with no TLS, suggesting rapid deployment infrastructure intended for short-lived campaigns.
| INDICATOR | TYPE | VALUE |
|---|---|---|
| Primary C2 | Domain | sfrclak[.]com |
| Secondary C2 | Domain | callnrwise[.]com |
| C2 IP | IPv4 | 142.11.206[.]73 |
| C2 Port | Port | 8000 (HTTP cleartext) |
| ASN | Network | AS54290 (Hostwinds LLC) |
| JARM | TLS | 28d28d28d00028d00028d28d28d28d96d86b34e11c2d3d5508f7111adf9d91 |
| JA3 | TLS | 656b9a2f4de6ed4909e157482860ab3d |
The C2 beacon uses a distinctive Internet Explorer 8 User-Agent string, a known Lazarus Group fingerprint also observed in previous DeceptiveDevelopment campaigns. All beacon payloads are base64-encoded JSON with type prefixes that produce stable, signaturable byte sequences.
maldet Signatures
We published 33 signatures across four detection layers, providing exact-match coverage for all known artifacts and behavioral detection that survives repackaging and minor code changes. All signatures passed false positive testing against 166,059 benign files across three engines ( ClamAV, YARA, maldet).
Hash Signatures (22)
Exact-match detection for all known artifacts. SHA256 entries cover all 16 verified hashes; MD5 entries cover the 6 artifacts with confirmed MD5 values.
| ARTIFACT | TYPE | SIGNATURE NAME |
|---|---|---|
| setup.js dropper | MD5+SHA256 | js.dropper.axios |
| axios@1.14.1 .tgz | SHA256 | js.supply.axios.v1141 |
| axios@0.30.4 .tgz | SHA256 | js.supply.axios.v0304 |
| plain-crypto-js .tgz | SHA256 | js.supply.axios.plaincrypto |
| system.bat | MD5+SHA256 | data.dropper.axios.winbat |
| persistence.bat | MD5+SHA256 | data.dropper.axios.persist |
| PowerShell RAT | MD5+SHA256 | data.backdoor.axios.psrat |
| macOS universal | MD5+SHA256 | bin.backdoor.nukesped.axios |
| macOS x86_64 | SHA256 | bin.backdoor.nukesped.x64 |
| macOS ARM64 | SHA256 | bin.backdoor.nukesped.arm64 |
| macOS variant 2 | SHA256 | bin.backdoor.nukesped.v2 |
| macOS stripped | SHA256 | bin.backdoor.nukesped.stripped |
| Linux ld.py | MD5+SHA256 | python.backdoor.axios |
| Shellcode 1 | SHA256 | bin.exploit.axios.sc1 |
| Shellcode trampoline | SHA256 | bin.exploit.axios.tramp |
| C2 response | SHA256 | data.backdoor.axios.c2resp |
Hex Pattern Signatures (4)
Single-pattern rules targeting campaign-specific strings that are unique enough to stand alone without false positive risk.
| PATTERN | DETECTS | NAME |
|---|---|---|
| OrDeR_7077 | XOR obfuscation key | js.dropper.axios.xorkey |
| sfrclak.com | Primary C2 domain | multi.backdoor.axios.c2pri |
| callnrwise.com | Secondary C2 domain | multi.backdoor.axios.c2sec |
| /packages.npm.org/product | Fake npm URI path | multi.backdoor.axios.c2uri |
Compound Signatures (7)
Boolean AND/OR rules that detect behavioral patterns even when exact hashes change. Each rule requires multiple campaign-specific indicators to be present in the same file, eliminating false positive risk from individual string matches.
| LOGIC | DETECTS | NAME |
|---|---|---|
| OrDeR_7077 AND plain-crypto-js | Dropper with XOR engine + package ref | js.dropper.axios |
| macWebT AND Jain_DEV | macOS binary build artifacts | bin.backdoor.nukesped.build |
| Extension.SubRoutine AND (macWebT OR com.apple.act.mond) | .NET class anchored to macOS indicators | bin.backdoor.nukesped.dotnet |
| (sfrclak.com OR callnrwise.com) AND 2-of-3 beacon types | Python RAT with C2 + beacon constants | python.backdoor.axios |
| IE8 User-Agent AND base64 beacon prefix | C2 beacon in captured traffic/logs | data.backdoor.axios.c2beacon |
| 6202033 AND MicrosoftUpdate AND (*.vbs OR *.ps1) | Windows persistence with campaign ID | data.backdoor.axios.winpersist |
| plain-crypto-js AND postinstall | Compromised package.json with malicious dep | js.supply.axios.pkg |
Detection & Remediation
If you installed or built with axios between 00:21 and 03:29 UTC on March 31, 2026, check your lockfiles and scan your systems:
1. Check Lockfiles
# Search for compromised versions in lockfiles
grep -r '"axios": "1.14.1\|"axios": "0.30.4\|plain-crypto-js' \
package-lock.json yarn.lock pnpm-lock.yaml 2>/dev/null
# Check npm cache for malicious packages
find ~/.npm/_cacache -name "*.tgz" -newer /tmp/marker 2>/dev/null | \
xargs -I{} sha256sum {} | \
grep -E '5bb67e88|59336a96|58401c19'2. Scan with maldet
# Update maldet signatures (includes all 33 new rules)
maldet -u
# Scan node_modules and temp directories
maldet -a /path/to/project/node_modules /tmp
# Scan CI/CD build directories
maldet -a /home/*/builds /var/lib/jenkins3. Check for RAT Artifacts
# Linux RAT
ls -la /tmp/ld.py
# macOS persistence
ls -la /Library/Caches/com.apple.act.mond
launchctl list | grep act.mond
# Windows (PowerShell)
Get-ItemProperty -Path 'HKCU:\Software\Microsoft\Windows\CurrentVersion\Run' |
Select-String 'MicrosoftUpdate'
Test-Path 'C:\ProgramData\system.bat'
Test-Path 'C:\ProgramData\wt.exe'4. Network IOCs
# Search proxy/firewall logs for C2 domains
grep -E 'sfrclak\.com|callnrwise\.com' /var/log/squid/*.log
grep -E '142\.11\.206\.73' /var/log/nginx/access.log
# Search for C2 beacon User-Agent
grep 'msie 8.0.*windows nt 5.1.*trident/4.0' /var/log/*/access*.log5. Remediate
node_modules and reinstall from clean lockfileIOCs
File Hashes
| ARTIFACT | SHA256 |
|---|---|
| setup.js | e10b1fa84f1d6481625f741b69892780140d4e0e7769e7491e5f4d894c2e0e09 |
| axios@1.14.1 | 5bb67e88846096f1f8d42a0f0350c9c46260591567612ff9af46f98d1b7571cd |
| axios@0.30.4 | 59336a964f110c25c112bcc5adca7090296b54ab33fa95c0744b94f8a0d80c0f |
| plain-crypto-js | 58401c195fe0a6204b42f5f90995ece5fab74ce7c69c67a24c61a057325af668 |
| system.bat | f7d335205b8d7b20208fb3ef93ee6dc817905dc3ae0c10a0b164f4e7d07121cd |
| persistence.bat | e49c2732fb9861548208a78e72996b9c3c470b6b562576924bcc3a9fb75bf9ff |
| PS RAT | 617b67a8e1210e4fc87c92d1d1da45a2f311c08d26e89b12307cf583c900d101 |
| macOS universal | 92ff08773995ebc8d55ec4b8e1a225d0d1e51efa4ef88b8849d0071230c9645a |
| macOS x86_64 | 506690fcbd10fbe6f2b85b49a1fffa9d984c376c25ef6b73f764f670e932cab4 |
| macOS ARM64 | 4465bdeaddc8c049a67a3d5ec105b2f07dae72fa080166e51b8f487516eb8d07 |
| ld.py (Linux) | fcb81618bb15edfdedfb638b4c08a2af9cac9ecfa551af135a8402bf980375cf |
Network Indicators
| TYPE | VALUE |
|---|---|
| Domain | sfrclak[.]com |
| Domain | callnrwise[.]com |
| IPv4 | 142.11.206[.]73 |
| Port | 8000 |
| URI | /packages.npm.org/product0 |
| URI | /packages.npm.org/product1 |
| URI | /packages.npm.org/product2 |
| URI | /6202033 |
| JARM | 28d28d28d00028d00028d28d28d28d96d86b34e11c2d3d5508f7111adf9d91 |
| JA3 | 656b9a2f4de6ed4909e157482860ab3d |
File System Artifacts
| PLATFORM | PATH |
|---|---|
| npm | node_modules/plain-crypto-js/setup.js |
| Linux | /tmp/ld.py |
| macOS | /Library/Caches/com.apple.act.mond |
| Windows | C:\ProgramData\system.bat |
| Windows | C:\ProgramData\wt.exe |
| Windows | %TEMP%\6202033.vbs |
| Windows | %TEMP%\6202033.ps1 |
MITRE ATT&CK
| TECHNIQUE | ID | USAGE |
|---|---|---|
| Supply Chain Compromise: Compromise Software Dependencies | T1195.001 | Malicious axios versions inject plain-crypto-js dep |
| Command and Scripting Interpreter: JavaScript | T1059.007 | postinstall hook executes setup.js dropper |
| Obfuscated Files or Information | T1027 | XOR cipher with OrDeR_7077 key + constant 333 |
| Ingress Tool Transfer | T1105 | Downloads platform RAT from C2 via HTTP |
| Masquerading | T1036 | com.apple.act.mond mimics Apple daemon; wt.exe mimics Windows Terminal |
| Boot or Logon Autostart Execution: Registry Run Keys | T1547.001 | HKCU\...\Run\MicrosoftUpdate persistence |
| Application Layer Protocol: Web Protocols | T1071.001 | HTTP POST beacons with base64 JSON payloads |
| System Information Discovery | T1082 | FirstInfo/BaseInfo beacons collect host fingerprint |
| Execution: Command and Scripting Interpreter | T1059 | subprocess execution via Python RAT |
Conclusion
The axios compromise represents an escalation in npm supply chain attacks: a nation-state actor (Lazarus Group) targeting one of the most depended-upon packages in the JavaScript ecosystem with a cross-platform RAT deployment capability. The three-hour window was enough to reach CI/CD pipelines, build servers, and developer workstations across all three major operating systems.
The attack pattern (maintainer account hijack, malicious dependency injection via postinstall hook, XOR-obfuscated dropper, platform-specific payload delivery) is reusable against any npm package. The defense layers that matter:
package-lock.json and yarn.lock record SHA-512 integrity hashes. A compromised version with a different hash will fail install if the lockfile is committed and enforced via npm ci (not npm install).npm install --ignore-scripts in CI, then audit and selectively allow scripts with npm rebuild. Tools like Socket flag new install scripts added to existing packages.npm install executes. The 33 signatures published for this incident cover the full kill chain from dropper to RAT to C2 beacon artifacts.npm access ls-collaborators.All 33 maldet signatures are available in the current signature update. Run maldet --update-sigs to pull the latest definitions.