Skip to main content
rfxn
//
maldetmalwaresupply-chainnpmlazarusapt38

Axios npm Compromise: Lazarus Group Deploys Cross-Platform RAT

Ryan MacDonald14 min read

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:03sfrclak.com registered (C2 domain)
Mar 31 00:21axios@1.14.1 published (compromised)
Mar 31 00:21axios@0.30.4 published (compromised)
Mar 31 00:21plain-crypto-js@4.2.1 published (dropper)
Mar 31 ~02:00Community reports begin (GitHub #10604)
Mar 31 03:29Malicious 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.

1. COMPROMISENPM REGISTRY2. DROPPERPOSTINSTALL3. DEPLOYPLATFORM RAT4. C2EXFILTRATEnpm Registryaxios@1.14.1axios@0.30.450M weekly downloadsmaintainer account hijackplain-crypto-js@4.2.1malicious dependencysetup.jsXOR key: OrDeR_7077constant: 333c ^ key[(7*r²) % 10] ^ 333platform detection → download from C2Windows/product1 → system.bat→ wt.exe (PS renamed)Registry: MicrosoftUpdatemacOSNUKESPED/product0 → universal bincom.apple.act.mondXcode: macWebT / Jain_DEVLinux/product2 → /tmp/ld.pyPython RAT (subprocess)C2 Serversfrclak.comcallnrwise.com142.11.206.73:8000AS54290 HostwindsHTTP cleartextIE8 User-Agent spoofLazarus Group (DPRK / APT38) // NukeSped attribution by 4 AV engines

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):

javascript
// 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.

PLATFORMC2 ENDPOINTPAYLOAD
macOS/packages.npm.org/product0Universal Mach-O binary (NukeSped)
Windows/packages.npm.org/product1system.bat → PS RAT via wt.exe
Linux/packages.npm.org/product2ld.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.

INDICATORTYPEVALUE
Primary C2Domainsfrclak[.]com
Secondary C2Domaincallnrwise[.]com
C2 IPIPv4142.11.206[.]73
C2 PortPort8000 (HTTP cleartext)
ASNNetworkAS54290 (Hostwinds LLC)
JARMTLS28d28d28d00028d00028d28d28d28d96d86b34e11c2d3d5508f7111adf9d91
JA3TLS656b9a2f4de6ed4909e157482860ab3d

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.

ARTIFACTTYPESIGNATURE NAME
setup.js dropperMD5+SHA256js.dropper.axios
axios@1.14.1 .tgzSHA256js.supply.axios.v1141
axios@0.30.4 .tgzSHA256js.supply.axios.v0304
plain-crypto-js .tgzSHA256js.supply.axios.plaincrypto
system.batMD5+SHA256data.dropper.axios.winbat
persistence.batMD5+SHA256data.dropper.axios.persist
PowerShell RATMD5+SHA256data.backdoor.axios.psrat
macOS universalMD5+SHA256bin.backdoor.nukesped.axios
macOS x86_64SHA256bin.backdoor.nukesped.x64
macOS ARM64SHA256bin.backdoor.nukesped.arm64
macOS variant 2SHA256bin.backdoor.nukesped.v2
macOS strippedSHA256bin.backdoor.nukesped.stripped
Linux ld.pyMD5+SHA256python.backdoor.axios
Shellcode 1SHA256bin.exploit.axios.sc1
Shellcode trampolineSHA256bin.exploit.axios.tramp
C2 responseSHA256data.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.

PATTERNDETECTSNAME
OrDeR_7077XOR obfuscation keyjs.dropper.axios.xorkey
sfrclak.comPrimary C2 domainmulti.backdoor.axios.c2pri
callnrwise.comSecondary C2 domainmulti.backdoor.axios.c2sec
/packages.npm.org/productFake npm URI pathmulti.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.

LOGICDETECTSNAME
OrDeR_7077 AND plain-crypto-jsDropper with XOR engine + package refjs.dropper.axios
macWebT AND Jain_DEVmacOS binary build artifactsbin.backdoor.nukesped.build
Extension.SubRoutine AND (macWebT OR com.apple.act.mond).NET class anchored to macOS indicatorsbin.backdoor.nukesped.dotnet
(sfrclak.com OR callnrwise.com) AND 2-of-3 beacon typesPython RAT with C2 + beacon constantspython.backdoor.axios
IE8 User-Agent AND base64 beacon prefixC2 beacon in captured traffic/logsdata.backdoor.axios.c2beacon
6202033 AND MicrosoftUpdate AND (*.vbs OR *.ps1)Windows persistence with campaign IDdata.backdoor.axios.winpersist
plain-crypto-js AND postinstallCompromised package.json with malicious depjs.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

bash
# 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

bash
# 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/jenkins

3. Check for RAT Artifacts

bash
# 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

bash
# 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*.log

5. Remediate

Pin axios to 1.14.0 or 0.30.3 in your lockfiles
Delete node_modules and reinstall from clean lockfile
Rotate all credentials on affected systems (SSH keys, API tokens, database passwords)
Block C2 domains and IP at network perimeter
Review CI/CD pipeline logs for builds that ran during the 3-hour window

IOCs

File Hashes

ARTIFACTSHA256
setup.jse10b1fa84f1d6481625f741b69892780140d4e0e7769e7491e5f4d894c2e0e09
axios@1.14.15bb67e88846096f1f8d42a0f0350c9c46260591567612ff9af46f98d1b7571cd
axios@0.30.459336a964f110c25c112bcc5adca7090296b54ab33fa95c0744b94f8a0d80c0f
plain-crypto-js58401c195fe0a6204b42f5f90995ece5fab74ce7c69c67a24c61a057325af668
system.batf7d335205b8d7b20208fb3ef93ee6dc817905dc3ae0c10a0b164f4e7d07121cd
persistence.bate49c2732fb9861548208a78e72996b9c3c470b6b562576924bcc3a9fb75bf9ff
PS RAT617b67a8e1210e4fc87c92d1d1da45a2f311c08d26e89b12307cf583c900d101
macOS universal92ff08773995ebc8d55ec4b8e1a225d0d1e51efa4ef88b8849d0071230c9645a
macOS x86_64506690fcbd10fbe6f2b85b49a1fffa9d984c376c25ef6b73f764f670e932cab4
macOS ARM644465bdeaddc8c049a67a3d5ec105b2f07dae72fa080166e51b8f487516eb8d07
ld.py (Linux)fcb81618bb15edfdedfb638b4c08a2af9cac9ecfa551af135a8402bf980375cf

Network Indicators

TYPEVALUE
Domainsfrclak[.]com
Domaincallnrwise[.]com
IPv4142.11.206[.]73
Port8000
URI/packages.npm.org/product0
URI/packages.npm.org/product1
URI/packages.npm.org/product2
URI/6202033
JARM28d28d28d00028d00028d28d28d28d96d86b34e11c2d3d5508f7111adf9d91
JA3656b9a2f4de6ed4909e157482860ab3d

File System Artifacts

PLATFORMPATH
npmnode_modules/plain-crypto-js/setup.js
Linux/tmp/ld.py
macOS/Library/Caches/com.apple.act.mond
WindowsC:\ProgramData\system.bat
WindowsC:\ProgramData\wt.exe
Windows%TEMP%\6202033.vbs
Windows%TEMP%\6202033.ps1

MITRE ATT&CK

TECHNIQUEIDUSAGE
Supply Chain Compromise: Compromise Software DependenciesT1195.001Malicious axios versions inject plain-crypto-js dep
Command and Scripting Interpreter: JavaScriptT1059.007postinstall hook executes setup.js dropper
Obfuscated Files or InformationT1027XOR cipher with OrDeR_7077 key + constant 333
Ingress Tool TransferT1105Downloads platform RAT from C2 via HTTP
MasqueradingT1036com.apple.act.mond mimics Apple daemon; wt.exe mimics Windows Terminal
Boot or Logon Autostart Execution: Registry Run KeysT1547.001HKCU\...\Run\MicrosoftUpdate persistence
Application Layer Protocol: Web ProtocolsT1071.001HTTP POST beacons with base64 JSON payloads
System Information DiscoveryT1082FirstInfo/BaseInfo beacons collect host fingerprint
Execution: Command and Scripting InterpreterT1059subprocess 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:

Lockfile pinning with integrity hashes. Both 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).
Postinstall script auditing. Run 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.
File-level malware scanning. Run maldet on every system where npm install executes. The 33 signatures published for this incident cover the full kill chain from dropper to RAT to C2 beacon artifacts.
npm account security. Maintainers of high-download packages should enable two-factor authentication, use hardware security keys where possible, and audit publish access with npm access ls-collaborators.

All 33 maldet signatures are available in the current signature update. Run maldet --update-sigs to pull the latest definitions.

References

Incident Analysis

Threat Actor Attribution

Tooling and Detection

npm Security