A forensic scanner for the Axios NPM supply chain attack discovered in March 2026, ported from PowerShell to Python 3.9 for Linux environments.
Further reading: Axios Supply Chain Attack Pushes Cross-Platform Malware — The Hacker News
In late March 2026, malicious versions of the popular axios npm package (1.14.1 and 0.30.4) were published to the npm registry. These versions included a dependency on plain-crypto-js@4.2.1, a package that runs a postinstall dropper script (setup.js) on installation.
The dropper:
- Exfiltrates credentials (SSH keys, GitHub tokens,
.npmrc, AWS/GCP keys, kubeconfig) - Installs a persistent backdoor via cron, systemd timers, or shell RC injection
- Establishes an encrypted C2 (command-and-control) channel to
sfrclak.com/142.11.206.73:8000using XOR encoding (key:OrDeR_7077) - Drops ELF binaries or scripts in temp directories for later execution
Any developer who ran npm install with an affected axios version between 2026-03-31 00:21 UTC and patch availability should consider their machine compromised and all credentials on it exposed.
- Python 3.9 or later
- Standard library only — no
pip installrequired - Linux (Ubuntu, Debian, RHEL, Arch, etc.)
npminstalled (optional — checks 4 and its sub-checks degrade gracefully if absent)sscommand available (optional — falls back to/proc/net/tcpif absent)
python3 axios_scanner.py --path ~python3 axios_scanner.pyDefaults to / and expands it to all top-level directories, skipping /proc, /sys, /dev, /run, and /snap. You will be prompted to confirm before the scan starts.
python3 axios_scanner.py --path /home/user/projects /opt/appsusage: axios_scanner.py [-h] [--path PATH [PATH ...]] [--output DIR] [--threads N]
optional arguments:
--path PATH [PATH ...] Paths to scan (default: /)
--output DIR Output directory for reports (default: /tmp)
--threads N Parallel threads for checks 2 & 3 (default: 4)
python3 -m unittest discover -s tests -t . -v| Code | Meaning |
|---|---|
0 |
Clean — no evidence of compromise found |
1 |
Compromised — one or more checks found evidence |
Walks the specified paths looking for package.json files to identify all Node.js projects present on the system. Directories named node_modules are skipped to avoid false positives inside dependency trees. The discovered project list is passed to Checks 2 and 3.
Check 2 — Lockfile Analysis
Reads the lockfile for each discovered project (package-lock.json, yarn.lock, or pnpm-lock.yaml) and checks whether the resolved axios version is one of the two malicious versions (1.14.1 or 0.30.4), and whether plain-crypto-js@4.2.1 (the dropper) is present. This is the primary indicator that a project installed the malicious package.
Check 3 — Forensic Artifacts
Inspects each project's node_modules/plain-crypto-js/ directory for physical evidence:
- Presence of the
plain-crypto-jsdirectory itself - SHA-256 hash of
setup.jscompared against the known malicious hash (e10b1fa8...) — a mismatch flags it as a possible variant - Scans all
.jsfiles in the project for embedded C2 indicators (sfrclak.com,142.11.206.73)
Scans the npm package cache (~/.npm/_cacache/index-v5) for cached tarballs of plain-crypto-js@4.2.1 and malicious axios versions. Also checks the global npm installation directory (npm root -g) for globally installed copies. Even if node_modules/ has been deleted, the cache may retain evidence of the attack.
Scans temp directories (/tmp, /var/tmp, ~/.cache, ~/.local/share) for files created after the attack window start (2026-03-31 00:21 UTC):
- ELF binaries (detected by the
\x7fELFmagic header) → Critical - Suspicious scripts (
.sh,.py,.js,.pl) → High
Files pre-dating the attack window are ignored. Each flagged file includes its SHA-256 hash for further forensic analysis.
Checks four locations for attacker-planted persistence, all filtered to entries modified after the attack window:
crontab -l— user's crontab for entries referencing/tmp,node,npm, or.jsfiles- Cron files —
/etc/crontab,/etc/cron.d/,/etc/cron.daily/,/etc/cron.hourly/ - Systemd user units —
~/.config/systemd/user/for.serviceand.timerfiles with suspiciousExecStart=lines - Shell RC files —
~/.bashrc,~/.bash_profile,~/.profile,~/.zshrcfor injectedPATHentries or loader commands
The malware encodes its C2 callback data using XOR with key OrDeR_7077 and a bitmask of 333 & 0xFF (= 0x4D). This check scans binary and script files in temp and config directories, XOR-decodes their contents, and looks for the C2 domain (sfrclak.com) or IP (142.11.206.73) in the decoded output. Detection here means a dropped payload is actively configured to beacon home.
Looks for evidence the C2 channel was or is active:
- Active connections — runs
ss -tnp(falls back to/proc/net/tcp) and checks for established connections to142.11.206.73:8000→ Critical - Hosts file — reads
/etc/hostsfor entries mapping the C2 IP or domain → Critical - Syslog — scans
/var/log/syslogand/var/log/auth.logfor logged connections to either C2 indicator → High
Produces two output files in the specified --output directory (default /tmp), both set to chmod 600:
Technical Forensic Report (Axios-Scan-<hostname>-<timestamp>.txt)
A full investigator-grade report covering all findings, IOC reference data, a list of credentials at risk, and step-by-step remediation instructions.
Executive Security Briefing (ExecBriefing-<hostname>-<timestamp>.txt)
A non-technical summary showing a pass/fail table for all 8 checks, the overall verdict, and immediate action steps for security management. Includes a SHA-256 integrity hash of the technical report.
| Indicator | Value |
|---|---|
| Malicious axios versions | 1.14.1, 0.30.4 |
| Dropper package | plain-crypto-js@4.2.1 |
| Known setup.js SHA-256 | e10b1fa84f1d6481625f741b69892780140d4e0e7769e7491e5f4d894c2e0e09 |
| C2 domain | sfrclak.com |
| C2 IP | 142.11.206.73 |
| C2 port | 8000 |
| XOR key | OrDeR_7077 |
| XOR mask | 333 & 0xFF = 0x4D |
| Attack window start | 2026-03-31 00:21 UTC |
Immediate actions:
- Disconnect the machine from the network
- Do not continue using the machine for any work
- Notify your Security Incident Response team
- Preserve a forensic disk image before making changes
Within 24 hours — rotate all credentials on this machine:
- SSH private keys
- GitHub / GitLab / Bitbucket personal access tokens
- npm publish tokens
- AWS / GCP / Azure access keys
- Kubernetes kubeconfig tokens
- Docker registry credentials
- Any secrets in
.envfiles
Lockfile cleanup (even if clean — remove the malicious version):
npm install axios@latest
npm cache clean --force
rm -rf node_modules
npm install