How Malicious Axios Versions Hijacked NPM: A Deep Supply‑Chain Attack Analysis
StepSecurity uncovered a sophisticated supply‑chain attack on the popular Axios HTTP client where compromised maintainer credentials were used to publish malicious versions that injected a hidden postinstall RAT, evaded detection, and executed platform‑specific payloads before self‑destructing, prompting detailed forensic and remediation guidance.
In March 2026 StepSecurity detected two malicious releases of the widely used JavaScript HTTP client Axios (versions 1.14.1 and 0.30.4) that were published using stolen npm credentials of a core maintainer. The attacker added a fake dependency, [email protected], which never appears in the legitimate Axios source code and whose sole purpose is to run a postinstall script that drops a cross‑platform remote‑access trojan (RAT) targeting macOS, Windows, and Linux.
Attack Timeline
2026‑03‑30 05:57 UTC – A clean stub package [email protected] is published by a newly created account to establish a benign publishing history.
2026‑03‑30 23:59 UTC – The malicious version [email protected] is released, adding a postinstall: "node setup.js" hook.
2026‑03‑31 00:21 UTC – [email protected] is published from the compromised maintainer account, injecting plain-crypto-js@^4.2.1 as a runtime dependency.
2026‑03‑31 01:00 UTC – [email protected] is published on the legacy branch with the same malicious dependency.
2026‑03‑31 03:25 UTC – npm unpublishes the two malicious Axios versions and restores the latest tag to 1.14.0.
Attack Mechanics
Step 1 – Maintainer Account Hijack
The attacker compromised the npm account jasonsaayman, changed its email to a ProtonMail address, and used the stolen token to publish the malicious packages, bypassing the OIDC‑based trusted publisher flow used by legitimate releases.
// [email protected] — legitimate
"_npmUser": {
"name": "GitHub Actions",
"email": "[email protected]",
"trustedPublisher": { "id": "github", "oidcConfigId": "oidc:…" }
}
// [email protected] — malicious
"_npmUser": {
"name": "jasonsaayman",
"email": "[email protected]"
// no trustedPublisher, no gitHead
}Step 2 – Preparing the Malicious Dependency
The attacker published [email protected] that mimics the legitimate crypto-js package but adds a postinstall hook pointing to setup.js. A clean stub ( [email protected]) was released 18 hours earlier to create a believable history.
Masquerades as crypto-js with identical metadata and source files.
Contains postinstall: "node setup.js" to trigger the dropper.
Includes a fake package.md stub reporting version 4.2.0 for forensic evasion.
Step 3 – Injecting the Dependency into Axios
Both malicious Axios releases list plain-crypto-js@^4.2.1 as a dependency, while all other dependencies remain unchanged. During npm install [email protected], npm resolves and installs [email protected], then executes its postinstall script.
RAT Dropper Details
The setup.js dropper is a heavily obfuscated JavaScript file that decodes an array stq[] containing strings for commands, module names, and the C2 URL http://sfrclak.com:8000/6202033. It selects the platform via os.platform() and runs one of three payloads:
macOS : Writes an AppleScript to a temporary file and executes it with osascript, downloading a binary to /Library/Caches/com.apple.act.mond and launching it via /bin/zsh.
Windows : Copies powershell.exe to %PROGRAMDATA%\wt.exe, writes a VBScript that launches a hidden cmd.exe to fetch a PowerShell RAT from the C2, saves it as %TEMP%\6202033.ps1, and executes it with -ExecutionPolicy Bypass -WindowStyle Hidden. The VBScript self‑deletes.
Linux/Other : Uses execSync to curl a Python RAT to /tmp/ld.py and runs it with nohup python3.
Self‑Cleaning Techniques
After launching the platform payload, setup.js performs three forensic‑evasion steps:
Deletes itself ( fs.unlink(__filename)).
Removes the malicious package.json containing the postinstall hook.
Renames the clean package.md stub to package.json, reporting version 4.2.0.
Consequently, a post‑infection npm list shows a clean dependency tree, and standard npm audit does not reveal the compromise.
Runtime Verification with Harden‑Runner
StepSecurity used its open‑source Harden‑Runner in audit mode to capture every network connection, process creation, and file write during an npm install of the malicious Axios version. The run recorded two outbound C2 connections:
First connection (curl) occurs 1.1 seconds after npm install starts, before dependency resolution finishes.
Second connection (nohup) occurs 36 seconds later in a separate workflow step, confirming the second‑stage payload remains active after the installer exits.
The process tree shows the dropper spawning a detached nohup process (orphaned to PID 1), a known technique to evade attribution.
Indicators of Compromise (IOCs)
Malicious packages: [email protected] (shasum 2553649f...), [email protected] (shasum d6f3f62f...), [email protected] (shasum 07d889e2...).
C2 domain/IP: sfrclak.com / 142.11.206.73, URL http://sfrclak.com:8000/6202033.
Payload files: /Library/Caches/com.apple.act.mond (macOS), %PROGRAMDATA%\wt.exe (Windows persistence), /tmp/ld.py (Linux), temporary VBScript/Powershell files under %TEMP%.
Compromised maintainer accounts: jasonsaayman (email changed to [email protected]) and attacker‑controlled nrwise (email [email protected]).
Detection & Remediation
To determine if a project is affected, run:
npm list axios 2>/dev/null | grep -E "1\.14\.1|0\.30\.4"
grep -A1 "\"axios\"" package-lock.json | grep -E "1\.14\.1|0\.30\.4"Check for the presence of the injected dependency:
ls node_modules/plain-crypto-js && echo "potentially affected"If the RAT files exist, treat the system as fully compromised and rebuild from a known‑good state, rotating all secrets (npm tokens, cloud credentials, SSH keys, .env values).
Recommended remediation steps:
Downgrade Axios to a clean version (e.g., npm install [email protected] or npm install [email protected]) and pin it.
Add an overrides (or resolutions) block to force the clean version.
Remove the malicious plain-crypto-js directory and reinstall with --ignore-scripts to prevent re‑execution.
If RAT artifacts are found, assume full compromise, rebuild the environment, and rotate all credentials.
Audit CI/CD logs for any runs that installed the malicious Axios versions and rotate injected secrets.
Adopt --ignore-scripts in CI pipelines to block postinstall execution.
Block outbound traffic to the C2 domain/IP at the network/DNS layer (e.g., firewall rule or hosts file entry).
Community Recovery Measures
StepSecurity’s open‑source tools provide additional safeguards:
Package cooling period : New npm packages are blocked for a configurable window, preventing rapid adoption of freshly published malicious versions.
Real‑time malicious‑package database : Known bad packages are automatically flagged in PR checks, stopping their introduction.
AI Package Analyst : Continuously scores new releases for supply‑chain risk and alerts on suspicious behavior.
Dev Machine Guard : Monitors installed npm packages on developer workstations and surfaces any matches to known compromised packages.
These measures, combined with the forensic evidence and remediation guidance above, enable organizations to detect, contain, and recover from this sophisticated supply‑chain compromise.
Code Mala Tang
Read source code together, write articles together, and enjoy spicy hot pot together.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
