The Axios Supply Chain Attack: When 70 Million Weekly Downloads Become a Weapon

11 min read
supply-chain-securitynpmaxioscybersecuritynorth-koreaaptiamincident-response

The Breach Nobody Saw Coming

On March 31, 2026, at 00:21 UTC, an attacker published axios@1.14.1 to npm. Thirty-nine minutes later, they published axios@0.30.4. Both versions were tagged to ensure maximum distribution—latest and legacy—guaranteeing that most fresh installations would pull a backdoored release.

By the time security researchers flagged the compromise three hours later, an unknown number of developer workstations, CI/CD pipelines, and production systems had already installed the malicious package and deployed cross-platform Remote Access Trojans to Windows, macOS, and Linux environments.

The attack vector was surgical: a compromised maintainer account, a malicious dependency injection that left the package's source code unchanged, and a postinstall hook that executed silently during npm install with zero user interaction required.

Axios is one of the most depended-upon HTTP client libraries in the JavaScript ecosystem, with over 70 million weekly downloads. This wasn't a supply chain incident. It was a supply chain detonation.

If you're an IAM engineer, security architect, or anyone responsible for software supply chain risk, this case study matters. Not because Axios is uniquely vulnerable—it isn't—but because the attack pattern reveals systemic gaps in how we secure dependency ecosystems at scale.


Attack Timeline: 174 Minutes of Exposure

Attack Timeline - March 30-31, 2026 UTC

The attacker's preparation was methodical:

March 30, 05:57 UTCplain-crypto-js@4.2.0 is published by nrwise@proton.me. This is a clean decoy package designed to build registry history and reduce scrutiny. It does nothing malicious.

March 30, 23:59 UTCplain-crypto-js@4.2.1 is published. This version adds a postinstall hook (node setup.js) that executes during installation. The malicious payload is now armed but has no distribution mechanism yet.

March 31, 00:21 UTCaxios@1.14.1 is published using a compromised maintainer account (jasonsaayman). The package manifest is modified to add plain-crypto-js@^4.2.1 as a dependency. The Axios source code remains unchanged. The release is tagged latest, ensuring it becomes the default version for npm install axios.

March 31, 01:00 UTCaxios@0.30.4 is published with the same malicious dependency injection, tagged legacy to catch projects still using the older 0.30.x API.

March 31, 03:15 UTC — Security researchers detect the compromise. The packages are removed from npm's registry. The exposure window closes at 174 minutes.

During that window, any npm install, npm ci, or automated dependency update that resolved to axios@^1.14.0 or axios@^0.30.0 pulled the compromised version and executed the malicious postinstall hook.


Anatomy of the Attack: Multi-Stage Execution Chain

The compromise relies on a three-stage execution chain designed to evade detection and maximize blast radius.

Stage 1: Dependency Injection via Manifest-Only Modification

The attacker's approach was surgical. Instead of modifying Axios's source code—which would trigger diff-based detection and break build reproducibility—they injected a new dependency into the package manifest:

"dependencies": {
  "plain-crypto-js": "^4.2.1"
}

This dependency is never imported by Axios's runtime code. It exists solely to trigger an install-time script. The package's application logic remains identical to the legitimate release, meaning:

  • Unit tests pass
  • Integration tests pass
  • Visual inspection of source diffs shows no changes
  • Runtime behavior appears normal

The only indicator is the presence of an unexpected dependency in package.json.

Stage 2: Silent Execution via npm Postinstall Hook

When npm install axios runs, the package manager resolves and installs plain-crypto-js@^4.2.1 as a transitive dependency. That package declares a postinstall script:

"scripts": {
  "postinstall": "node setup.js"
}

This hook executes automatically during installation—no user interaction, no confirmation prompt, no warning. The script runs with the same privileges as the user who initiated the install.

The setup.js payload uses layered obfuscation to conceal its behavior:

Layer 1: String reversal + Base64 decoding
Layer 2: XOR cipher using the key OrDeR_7077 with position-dependent indexing

All critical strings (module names, URLs, shell commands) are stored in an encoded array and decoded at runtime. Once decoded, the script:

  1. Detects the operating system via os.platform()
  2. Constructs platform-specific HTTP POST request bodies
  3. Connects to http://sfrclak[.]com:8000/6202033 to fetch stage-2 payloads
  4. Executes the downloaded payload using platform-native mechanisms
  5. Performs anti-forensic cleanup (self-deletion, manifest swap)

The POST body varies by platform to enable the C2 server to serve the correct binary from a single endpoint:

  • macOS: packages.npm.org/product0
  • Windows: packages.npm.org/product1
  • Linux: packages.npm.org/product2

The packages.npm.org/ prefix is a deliberate attempt to make outbound traffic appear as benign npm registry communication in network logs.

Stage 3: Cross-Platform RAT Deployment

The C2 server responds with platform-specific stage-2 payloads. These are not three different tools—they are three implementations of the same Remote Access Trojan specification, sharing an identical C2 protocol, command set, and operational behavior.

Cross-Platform RAT Deployment Architecture

Shared characteristics across all three variants:

  • C2 transport: HTTP POST with Base64-encoded JSON bodies
  • User-Agent: mozilla/4.0 (compatible; msie 8.0; windows nt 5.1; trident/4.0) (IE8/Windows XP—anachronistic and immediately detectable on macOS/Linux)
  • Beacon interval: 60 seconds
  • Session UID: 16-character random alphanumeric string
  • Command types: kill, peinject, runscript, rundir

The Windows variant establishes persistence via a registry Run key and a hidden batch file in %PROGRAMDATA%\system.bat. The macOS and Linux variants operate as session-only implants with no built-in persistence.

All three support arbitrary script execution, binary payload injection, and filesystem enumeration. The operator can interactively browse the compromised system, execute code, and deploy additional tooling.


Attribution: North Korea's Sapphire Sleet (UNC1069)

Microsoft Threat Intelligence and Google's Threat Analysis Group publicly attributed this campaign to Sapphire Sleet (also tracked as UNC1069, STARDUST CHOLLIMA, Alluring Pisces, BlueNoroff), a North Korean state-sponsored threat actor active since at least March 2020.

Sapphire Sleet's primary motivation is financial: cryptocurrency theft to generate revenue for the DPRK regime. The group targets cryptocurrency exchanges, blockchain platforms, venture capital firms, and fintech organizations globally, with a particular focus on the United States, Asia, and the Middle East.

The macOS Mach-O binary delivered in this campaign exhibits significant code overlap with WAVESHAPER, a C++ backdoor previously attributed to UNC1069 by Mandiant. The shared infrastructure (Hostwinds VPS hosting, ProtonMail accounts, similar C2 domain patterns) further supports the attribution.

Sapphire Sleet is known for:

  • Social engineering via LinkedIn — targeting developers and security engineers with fake job offers, technical assessments, or collaboration requests
  • Malicious meeting links — impersonating Zoom, Google Meet, or other video conferencing platforms
  • Supply chain attacks — poisoning open-source packages, developer tools, and CI/CD dependencies

This Axios compromise follows the pattern of other high-profile supply chain attacks linked to DPRK-nexus actors, including the 2024 3CX compromise and multiple npm/PyPI package poisoning campaigns.


Detection and Response: What Security Teams Should Do Now

Immediate Actions

1. Audit installed Axios versions across all environments

Check developer workstations, CI/CD pipelines, staging, and production systems for the compromised versions:

# Find Axios installations
find . -type f -name package.json -exec grep -H "axios" {} \;

# Check for malicious versions
npm list axios --depth=0 | grep -E "1.14.1|0.30.4"

2. Search for the malicious dependency

# Check for plain-crypto-js
npm list plain-crypto-js --depth=0

3. Check network logs for C2 communication

Look for outbound connections to:

  • Domain: sfrclak[.]com
  • IP: 142.11.206.73
  • Port: 8000
  • Path: /6202033

4. Hunt for filesystem artifacts

PlatformIndicatorLocation
WindowsPowerShell payload%TEMP%\6202033.ps1
WindowsVBScript dropper%TEMP%\6202033.vbs
WindowsPersistence batch%PROGRAMDATA%\system.bat
WindowsRenamed PowerShellC:\ProgramData\wt.exe
WindowsRegistry persistenceHKCU:\Software\Microsoft\Windows\CurrentVersion\Run\MicrosoftUpdate
macOSBinary RAT/Library/Caches/com.apple.act.mond
LinuxPython loader/tmp/ld.py

5. Rotate credentials immediately

Assume any secrets, API keys, or credentials exposed to compromised systems have been exfiltrated. This includes:

  • Environment variables
  • Configuration files
  • CI/CD secrets
  • Cloud service credentials
  • SSH keys
  • Application secrets

Mitigation Strategies

Pin exact versions in package.json

Remove caret (^) and tilde (~) version specifiers to disable automatic updates:

{
  "dependencies": {
    "axios": "1.14.0"
  }
}

Use npm overrides to force pinned versions

This prevents transitive dependencies from upgrading Axios:

{
  "overrides": {
    "axios": "1.14.0"
  }
}

Disable postinstall hooks when possible

If your workflow allows, prevent install-time scripts from executing:

npm ci --ignore-scripts

Or globally:

npm config set ignore-scripts true

Adopt npm provenance and OIDC publishing

Legitimate Axios releases before the compromise were published via GitHub Actions with OIDC and SLSA provenance attestations. The malicious versions used direct CLI publishing with no provenance.

Organizations should prioritize packages that use trusted publishing flows and verify provenance when available.

Monitor dependency changes in CI/CD

Implement automated checks that flag:

  • New dependencies added to manifests
  • Version bumps during automated updates
  • Changes to postinstall hooks
  • Packages with missing or unverified provenance

Long-Term Supply Chain Hardening

This attack exposes structural weaknesses in the npm ecosystem that go beyond any single package:

1. Maintainer account security is a single point of failure

A compromised email address, weak 2FA, or leaked credentials can give an attacker publishing rights to millions of downstream users. The npm ecosystem needs:

  • Mandatory hardware-based 2FA for maintainers of high-impact packages
  • Account activity monitoring and anomaly detection
  • Publishing guardrails (e.g., require multiple maintainer approvals for releases of critical packages)

2. Postinstall hooks are an under-constrained attack surface

The ability to execute arbitrary code during package installation—with no sandboxing, no permission model, and no user confirmation—is a fundamental design flaw. The ecosystem needs:

  • Opt-in install hooks (require explicit consent in package.json)
  • Sandboxed execution environments with capability-based permissions
  • Static analysis of install scripts prior to execution

3. Dependency verification is not the default

Most projects install dependencies without verifying signatures, provenance, or integrity beyond basic checksums. Organizations should:

  • Require signed commits and signed releases
  • Validate SLSA provenance attestations when available
  • Use tools like Sigstore to verify package authenticity

4. Supply chain visibility is blind to transitive dependencies

The malicious code was in plain-crypto-js, not Axios itself. Most dependency scanners and SBOMs don't provide real-time visibility into transitive dependency changes. Security teams need:

  • Continuous monitoring of the full dependency graph
  • Alerting on new transitive dependencies
  • Automated diff analysis of package manifests across deployments

What This Means for IAM and Security Engineers

If you're responsible for identity governance, access management, or enterprise security, this incident should inform your threat model in three ways:

1. Developer workstations are privileged endpoints

Engineers with access to production secrets, CI/CD pipelines, or cloud infrastructure are high-value targets. A compromised developer machine can pivot to production environments, exfiltrate credentials, and persist undetected.

IAM teams should treat developer endpoints as privileged access workstations (PAWs) and enforce:

  • Conditional access policies based on device posture
  • Just-in-time credential provisioning
  • Zero standing secrets in development environments

2. CI/CD pipelines are identity chokepoints

Build systems often run with elevated privileges and have access to secrets across multiple environments. A single compromised dependency in a CI/CD context can:

  • Exfiltrate deployment credentials
  • Inject backdoors into build artifacts
  • Establish persistence in production infrastructure

Consider:

  • Isolating build environments with ephemeral, non-reusable credentials
  • Implementing provenance tracking for all build artifacts
  • Using workload identity federation to eliminate static secrets

3. Supply chain compromise is an identity attack vector

Attackers increasingly use compromised open-source packages to harvest credentials, API keys, and cloud access tokens. This shifts supply chain security from "code review and vulnerability scanning" to "identity and access management."

Security teams should:

  • Inventory all credentials exposed to build and development environments
  • Implement secret rotation policies that account for supply chain exposure
  • Monitor for anomalous credential usage patterns that could indicate compromise

Conclusion: The Cost of Implicit Trust

The Axios supply chain attack succeeded because the npm ecosystem operates on implicit trust. We trust maintainer accounts. We trust postinstall hooks. We trust that packages with millions of downloads have sufficient security oversight.

This attack cost the maintainer nothing—they didn't realize their account was compromised until researchers flagged the malicious releases. It cost the attacker minimal effort—a single account takeover, a dependency injection, and 174 minutes of exposure were enough to deploy cross-platform RATs to an unknown number of systems.

And it will cost the ecosystem immeasurably more in incident response, credential rotation, forensic analysis, and lost trust.

The technical indicators—network IOCs, filesystem artifacts, registry keys—are important for detection and response. But the strategic lesson is simpler: supply chain security cannot rely on post-incident cleanup. It requires structural changes to how we publish, verify, and consume dependencies.

If you're an IAM engineer, this is your problem too. The next compromised package might target your build pipelines, your cloud credentials, or your identity infrastructure.

The question isn't whether the next supply chain attack will happen. It's whether your organization will detect it in 174 minutes or 174 days.


References