Product Security

Inside the Axios Supply Chain Attack: How North Korea Weaponized npm Against 100 Million Developers

On March 30, 2026, a North Korean state actor compromised the npm account of the lead maintainer of axios, the most widely used HTTP client in the JavaScript ecosystem. Within 39 minutes, they published two backdoored versions across both the current and legacy release branches. Every developer and CI/CD pipeline that ran npm install during the next three and a half hours received a cross-platform remote access trojan that worked on macOS, Windows, and Linux.

Axios has over 100 million weekly downloads. It is a transitive dependency of thousands of other packages. Huntress observed at least 135 compromised endpoints within their partner base alone. Microsoft Threat Intelligence attributed the attack to Sapphire Sleet, a North Korean state-sponsored group also tracked as UNC1069 by Google Threat Intelligence. This was not a lone-wolf campaign. It was a nation-state operation targeting the software supply chain at its most critical node.

The attack was over in three and a half hours. The damage is still being assessed. If your organization builds or deploys JavaScript applications, this is the moment to audit your dependency pipeline.

The Attack Timeline

The operation was pre-staged across 18 hours. The attackers seeded the malicious dependency on npm before publishing the compromised axios versions, a deliberate move to avoid triggering "brand-new package" alarms at the moment of the actual attack.

On March 30 at 05:57 UTC, an account registered under the email nrwise@proton.me published a package called plain-crypto-js@4.2.0. This was a clean decoy, containing no malicious code. Its only purpose was to establish registry history so the package would not look suspicious when the malicious version appeared hours later.

At 23:59 UTC, the same account published plain-crypto-js@4.2.1. This version contained the payload: a postinstall hook that executed node setup.js, which dropped and ran a platform-specific RAT binary. Six minutes later, automated npm security scanners flagged it as malware. But the next step had already begun.

At 00:21 UTC on March 31, the compromised jasonsaayman account published axios@1.14.1 and tagged it latest. Thirty-nine minutes later, axios@0.30.4 followed, poisoning the legacy 0.x branch. Both versions added plain-crypto-js as a dependency. It was never imported in code. Its sole purpose was to execute the postinstall hook.

At approximately 03:30 UTC, the npm security team removed all compromised packages and revoked the maintainer tokens. The exposure window was three hours and nine minutes.

How the RAT Worked

The payload was sophisticated in both delivery and cleanup. When npm install processed the plain-crypto-js dependency, the postinstall hook ran setup.js. This script detected the host operating system and downloaded a platform-specific binary from the attacker's command-and-control server at sfrclak.com (IP: 142.11.206.73).

On macOS, the RAT was delivered as a Mach-O binary written to /tmp/.n and executed with nohup to survive terminal closure. On Windows, it was a PE binary dropped to %TEMP%. On Linux, an ELF binary followed the same pattern. All three variants established persistent C2 communication and were capable of credential theft, file exfiltration, and remote command execution.

After execution, the malware replaced its own files with clean decoys. The setup.js script was overwritten with benign content, and the malicious binary was deleted. This anti-forensic step meant that a developer who checked their node_modules directory after infection would see nothing suspicious. The payload was already running in memory, and the evidence on disk was gone.

Why This Attack Was Different

Supply chain attacks against npm are not new. Typosquatting campaigns and malicious packages appear on the registry regularly. What made the axios compromise different was its strategic precision.

First, the attackers targeted the single most depended-upon HTTP library in the JavaScript ecosystem. This guaranteed maximum propagation. Any package that transitively depends on axios and uses a semver range like ^1.14.0 in its package.json would have automatically pulled the compromised version.

Second, they bypassed npm's Trusted Publisher safeguards. The axios project uses GitHub Actions with OIDC-based publishing, which is supposed to prevent unauthorized releases by tying npm publishes to verified CI/CD pipelines. The attackers circumvented this entirely by using a stolen npm token to publish directly, leaving no trace in the GitHub repository's commit history or Actions logs. The malicious versions existed only on the npm registry.

Third, the attack was timed to maximize dwell time. The malicious packages were published just after midnight UTC on a Sunday. Maintainer response and npm security team intervention were delayed by hours, which is exactly what the attackers planned. Huntress recorded the first infection 89 seconds after the latest tag was applied.

Fourth, the supply chain propagation was transitive. Huntress confirmed infections arriving through completely unrelated packages, including WordPress tooling and Datadog integrations, because those packages depended on axios somewhere in their dependency tree. A developer who never directly installed axios could still be compromised.

Checking If You Were Affected

Any system that installed axios@1.14.1 or axios@0.30.4 between March 30 23:59 UTC and March 31 03:30 UTC should be treated as fully compromised. The RAT's credential theft capabilities mean the blast radius extends beyond the infected machine to every service those credentials accessed.

# Check your lockfiles for compromised versions
grep -r "axios@1.14.1\|axios@0.30.4\|plain-crypto-js" package-lock.json yarn.lock pnpm-lock.yaml 2>/dev/null

# Check npm cache for evidence of the malicious package
find ~/.npm/_cacache -name "*.tgz" 2>/dev/null | xargs strings 2>/dev/null | grep -l "plain-crypto-js"

# Check for C2 connections in network logs
# Look for DNS queries or connections to:
#   sfrclak.com
#   142.11.206.73

If you find evidence of the compromised versions, assume full compromise. Rotate all credentials on the affected machine: npm tokens, GitHub PATs, cloud API keys, SSH keys, database passwords, and any secrets stored in environment variables or CI/CD configurations. Reimage the machine. Do not attempt to clean it in place.

Hardening Your npm Pipeline

The axios attack exploited the most common default configuration in the JavaScript ecosystem: automatic semver-range resolution with unrestricted postinstall script execution. These are the specific steps to close that attack surface.

1. Disable postinstall scripts by default. The entire axios attack chain depended on the postinstall hook in plain-crypto-js executing automatically. Only 2.2% of npm packages use install scripts. Disabling them by default breaks almost nothing and blocks the most common supply chain payload delivery mechanism.

# Set globally (protects all projects on this machine)
npm config set ignore-scripts true

# Set per-project (.npmrc in project root)
echo "ignore-scripts=true" >> .npmrc

# When you need scripts for a specific trusted package, use:
# npx --yes @lavamoat/allow-scripts

2. Use npm ci in every CI/CD pipeline. The command npm ci installs from the lockfile exactly as written. It does not resolve new versions. If your lockfile pins axios@1.13.0 and the attacker publishes 1.14.1, npm ci ignores it. The command npm install would resolve the new version based on the semver range and install the backdoor.

# In your CI/CD pipeline, always use:
npm ci --ignore-scripts

# Never use npm install in CI/CD
# Never use npm update in CI/CD without human review

3. Commit your lockfile. If package-lock.json is in your .gitignore, fix that immediately. The lockfile is your defense against automatic version resolution. Without it, every npm install is a fresh resolution that can pull in compromised versions.

4. Enforce a release cooldown period. Configure your npm client or private registry to delay installation of packages published within the last 72 hours. The axios attack was detected and remediated in 3.5 hours, but many supply chain attacks survive longer. A 72-hour delay gives the community and automated scanners time to flag malicious releases before they reach your pipeline.

# In .npmrc (requires npm 10+)
# Set minimum release age to 3 days
before=3d

5. Enforce phishing-resistant MFA on all publishing accounts. The axios maintainer's npm account was compromised through credential theft. Hardware security keys (FIDO2/WebAuthn) are the only MFA method that resists phishing. If your team maintains any open-source package, require hardware keys for all accounts with publish permissions.

6. Run dependency audits in CI. Integrate npm audit or a Software Composition Analysis tool into your CI pipeline as a blocking check. Flag any new dependency or version change for manual review. Treat lockfile changes with the same scrutiny as production code changes.

# Add to CI pipeline
npm audit --audit-level=moderate

# Fail the build if any known vulnerability is found
# Review and explicitly allow known issues via:
npm audit fix --dry-run

7. Block known C2 infrastructure at the network level. Add the attacker's domain and IP to your DNS blocklist and firewall rules. For the axios attack specifically, block sfrclak.com and 142.11.206.73. More broadly, maintain a blocklist of known malicious infrastructure from threat intelligence feeds.

The Broader Pattern

The axios compromise was not an isolated incident. It was part of a broader campaign. In the eight days between March 19 and March 27, a group tracked as TeamPCP executed a cascading supply chain attack that chained from Aqua Security's Trivy vulnerability scanner to LiteLLM to axios to Mercor, hitting five ecosystems in eight days. Each compromised tool was used to pivot to the next target.

This is the emerging model for software supply chain attacks: cascading compromise through transitive trust. You do not need to use axios directly to be affected by the axios attack. You need only to use a package that uses a package that uses axios. The median JavaScript project has over 200 transitive dependencies. Any one of them is a potential entry point.

For organizations building software in 2026, supply chain security is no longer optional. It is the perimeter. And unlike the network perimeter, it runs through every npm install on every developer machine and every CI runner in your pipeline.

Need a supply chain security assessment?

We audit dependency pipelines, CI/CD configurations, and development workflows for the security gaps that supply chain attackers exploit. If your organization builds or deploys JavaScript applications, we can map your exposure and help you implement the hardening steps that actually matter. Book a session to discuss your pipeline.