axios Supply Chain Attack Alert

[Urgent Alert] axios Poisoned! Check Your package.json Immediately

Security

[Urgent Alert] axios Poisoned! Check Your package.json Immediately

Event Nature: npm Supply Chain Poisoning Attack Affected Versions: [email protected], [email protected] Attack Time: March 31, 2026 Threat Level: πŸ”΄ Critical Reading Time: ~10 mins | Word Count: ~4500

axios Supply Chain Attack Alert


01. Urgent Self-Check & Remediation (Must Read)

Affected Versions

BranchMalicious VersionSafe Version
1.x1.14.11.14.0
0.x0.30.40.30.3

One-Click Self-Check Commands

πŸ” Single Project Check (Run in Project Root)

Check Dependency Version:

Terminal window
# Check the currently installed axios version
npm list axios 2>/dev/null | grep -E "1\.14\.1|0\.30\.4"
# Check package-lock.json
grep -A1 '"axios"' package-lock.json | grep -E "1\.14\.1|0\.30\.4"
# Check if the malicious dependency directory exists
ls node_modules/plain-crypto-js 2>/dev/null && echo "⚠️ plain-crypto-js detected, system may be infected"

🌐 Global Batch Check (Scan All Projects on Your Computer)

Run in your code root directory (e.g., ~/Projects or ~/Documents):

macOS / Linux:

Terminal window
# 1. Batch find malicious packages in all node_modules
find . -name "plain-crypto-js" -type d 2>/dev/null | grep "node_modules" && echo "⚠️ Malicious dependency detected"
# 2. Batch find malicious versions in package-lock.json
grep -rE '"axios":.*(1\.14\.1|0\.30\.4)"' . --include="package-lock.json"

Windows (PowerShell):

Terminal window
# 1. Batch find malicious dependency directories
Get-ChildItem -Path . -Directory -Recurse -Filter "plain-crypto-js" -ErrorAction SilentlyContinue | Where-Object { $_.FullName -match "node_modules" }
# 2. Batch find malicious versions
Get-ChildItem -Path . -File -Recurse -Filter "package-lock.json" | Select-String -Pattern 'axios.*1\.14\.1|axios.*0\.30\.4'

πŸ–₯️ System-Level RAT Check (Critical)

PlatformCheck CommandInterpretation
macOS`[ -e β€œ/Library/Caches/com.apple.act.mond” ] && echo β€πŸš¨ INFECTED”
Linux`[ -e β€œ/tmp/ld.py” ] && echo β€πŸš¨ INFECTED”
WindowsTest-Path "$env:PROGRAMDATA\wt.exe"Check %PROGRAMDATA%\wt.exe

One-Click Detection Script:

Terminal window
# macOS / Linux Universal Version
check_rat() {
if [ "$(uname)" = "Darwin" ]; then
[ -e "/Library/Caches/com.apple.act.mond" ] && echo "🚨 macOS RAT file exists, system compromised!" || echo "βœ… macOS Safe"
else
[ -e "/tmp/ld.py" ] && echo "🚨 Linux RAT file exists, system compromised!" || echo "βœ… Linux Safe"
fi
}
check_rat
Terminal window
# Windows PowerShell Version
if (Test-Path "$env:PROGRAMDATA\wt.exe") {
Write-Host "🚨 Windows RAT file exists, system compromised!" -ForegroundColor Red
} else {
Write-Host "βœ… Windows Safe" -ForegroundColor Green
}

Remediation Steps

Step 1: Pin Version to Safe Range

Single Project Fix:

Terminal window
# 1.x Users
npm install [email protected] --save-exact
# 0.x Users
npm install [email protected] --save-exact

Batch Fix Multiple Projects (Run in code root):

Terminal window
# Batch pin all projects to 1.14.0
find . -name "package.json" -not -path "*/node_modules/*" -execdir npm install [email protected] --save-exact --ignore-scripts \;

πŸ’‘ Parameter Explanation:

  • --save-exact: Pins the exact version (1.14.0 instead of ^1.14.0)
  • --ignore-scripts: Prevents the postinstall hook from triggering again

Add manual overrides in package.json to enforce the version (covering indirect dependencies):

{
"dependencies": {
"axios": "1.14.0"
},
"overrides": {
"axios": "1.14.0"
},
"resolutions": {
"axios": "1.14.0"
}
}

Step 2: Remove node_modules and Reinstall

Terminal window
rm -rf node_modules package-lock.json
npm install --ignore-scripts

⚠️ --ignore-scripts is crucial to prevent the malicious hook from running during reinstall.

Step 3: Scan for System Residual Files

PlatformPath to CheckAction
macOS/Library/Caches/com.apple.act.mondIf exists β†’ System compromised, rebuild required
Windows%PROGRAMDATA%\wt.exeIf exists β†’ System compromised, rebuild required
Linux/tmp/ld.pyIf exists β†’ System compromised, rebuild required

🚨 If RAT Files Are Found:

  • DO NOT attempt local cleanup β€” The RAT may have established persistence or moved laterally.
  • Rebuild the machine from a trusted image.
  • Rotate all credentials: npm tokens, GitHub tokens, AWS keys, cloud credentials, CI/CD secrets, .env files.

02. Impact Scope

Impact Scope Infographic

Risks of 100M+ Weekly Downloads

axios is one of the most popular HTTP clients in the JavaScript ecosystem:

MetricData
Weekly Downloads83M+
Dependent Projects174,025
CoverageFrontend frameworks, backend services, enterprise apps, mobile

Exposure Window: 2026-03-31 00:21 UTC ~ 08:00 UTC (approx. 8 hours)

Any project that ran npm install axios or npm update during this window may be infected.

Why CI/CD Pipelines are the Hardest Hit

This attack is particularly devastating for CI/CD environments:

  1. Automatic Trigger β€” Pipelines run npm install on every build, automatically executing the postinstall hook.
  2. High-Privilege Access β€” CI runners often have production deployment permissions and access to sensitive secrets.
  3. Difficult Traceability β€” Evidence is lost once temporary build environments are destroyed.
  4. Lateral Movement β€” Infected CI systems may deploy malicious code to all downstream environments.

Check your CI/CD:

Terminal window
# Audit GitHub Actions logs for the malicious version
grep -r "[email protected]\|[email protected]" .github/workflows/
# Consider any runner active during this window as compromised.

03. Attack Technique Deep Dive

Attack Chain Flowchart

Hijacking Maintainer Account: The Origin

The attacker targeted the npm account of jasonsaayman, a primary axios maintainer:

  1. Account Tampering β€” Changed the registered email to an attacker-controlled ProtonMail: [email protected].
  2. Token Acquisition β€” Used a long-lived Classic npm access token.
  3. Bypassing CI/CD β€” Published directly via the npm CLI, skipping the GitHub Actions OIDC trusted publishing mechanism.

Key Evidence: There are no 1.14.1/0.30.4 records on the GitHub Releases page, indicating this was not published through the normal CI process.

Malicious Dependency plain-crypto-js: The Hidden Trojan Downloader

The attacker orchestrated a Phantom Dependency attack:

Clean [email protected] dependencies:
β”œβ”€β”€ follow-redirects
β”œβ”€β”€ form-data
└── proxy-from-env
Malicious [email protected] dependencies:
β”œβ”€β”€ follow-redirects
β”œβ”€β”€ form-data
β”œβ”€β”€ proxy-from-env
└── plain-crypto-js@^4.2.1 ← The only new addition

Key Point: A search of all 86 source files in axios reveals zero references to plain-crypto-js. Its sole purpose is to trigger the postinstall hook.

Obfuscation in the setup.js Dropper:

  • Two-layer obfuscation: XOR + Base64.
  • Sensitive strings decoded at runtime.
  • Decryption key: "OrDeR_7077".

The decoded core strings include the C2 address http://sfrclak.com:8000/ and multi-platform payloads.

Self-Cleaning Mechanism: Why You Can’t Find It?

This is the most cunning part of the attack β€” self-destruction after execution:

After setup.js runs:
1. fs.unlink(__filename) β†’ Deletes itself
2. fs.unlink("package.json") β†’ Deletes the manifest containing postinstall
3. fs.rename("package.md", "package.json") β†’ Replaces it with a clean stub

The attacker pre-packaged a clean package.md (version 4.2.0, no postinstall hook) and renamed it to package.json after the malicious code ran.

Result: During post-incident inspection, package.json looks perfectly normal with no suspicious scripts.

Detection Hint: Even if package.json is restored, the presence of the node_modules/plain-crypto-js/ directory confirms the infection.


04. Defense Recommendations

npm Security Defense Framework

Stop Trusting latest

This attack is another wake-up call: Never use the latest tag in production.

// ❌ Dangerous
{
"dependencies": {
"axios": "latest"
}
}
// βœ… Recommended
{
"dependencies": {
"axios": "1.14.0"
}
}

How to Configure npm Security Policies

1. Lock Dependency Versions

Terminal window
# Use exact versions
npm install [email protected] --save-exact
# Or configure in .npmrc
save-exact=true

2. Disable Lifecycle Scripts

.npmrc
ignore-scripts=true
# Or specify during install
npm install --ignore-scripts

3. Enable Security Audits

Terminal window
# Add to CI
npm audit --audit-level=high
# Auto-fix with npm audit fix
npm audit fix

4. Use Lockfiles

Terminal window
# Always commit package-lock.json
# Use npm ci instead of npm install in CI
npm ci --ignore-scripts

5. Monitor Dependency Changes

Terminal window
# Check dependency tree changes
npm ls --depth=0
# Use tools for monitoring
npx npm-check-updates

6. Network-Level Blocking

Terminal window
# Block known C2 domains
echo "0.0.0.0 sfrclak.com" | sudo tee -a /etc/hosts

Summary

Key PointAction Item
πŸ”΄ Check NowRun self-check commands, confirm axios version
🟠 If InfectedDowngrade version + Remove node_modules + Rotate credentials
🟒 Long-term FixLock versions + Disable scripts + Enable auditing

Remember: Supply chain attacks don’t need vulnerabilities in your code; they only need your trusted dependencies to be compromised. Today it’s axios; tomorrow it could be another package.

Published at: Apr 2, 2026 Β· Modified at: Apr 2, 2026