axios Compromised on npm: What Every JS Dev Needs to Check Now

If your project uses axios — and if you work with JavaScript, you probably do — this concerns you directly.

In the early morning hours of March 31st (UTC), an attacker compromised the npm account of axios’s primary maintainer, published two poisoned versions of the library, and removed them before most teams in the Americas arrived at their offices. The exposure window was approximately three hours. Axios has over 100 million weekly downloads. The scale of potential risk is difficult to underestimate.


What Exactly Happened

The attacker did not modify axios’s source code. Instead, they compromised the npm account of jasonsaayman, the primary maintainer, changed the registered email to a ProtonMail address to lock him out, and published two releases manually via CLI — completely bypassing the project’s GitHub Actions CI/CD pipeline.

The malicious dependency was prepared 18 hours in advance. Three separate payloads were pre-built for three operating systems. Both release branches were affected within a 39-minute window.

The compromised versions are axios@1.14.1 and axios@0.30.4. Both inject a new dependency: plain-crypto-js@4.2.1, a package that never existed before March 30th and is not imported anywhere in axios’s actual code. Its sole purpose is to execute a postinstall script that acts as a dropper for a cross-platform RAT, targeting macOS, Windows, and Linux.


The Mechanism: Why postinstall Is So Dangerous

When you run npm install, npm automatically executes scripts defined in package.json of each dependency — including transitive ones. You don’t need to import plain-crypto-js in your code. You don’t need to know it exists. It just needs to be in your dependency tree for its script to execute with your session’s privileges, on your machine or in your CI/CD runner.

StepSecurity confirmed the malware’s operation through runtime analysis using their Harden-Runner tool: a connection to the C2 domain was detected just 1.1 seconds after running npm install.

The dropper then self-deletes — it removes setup.js and replaces package.json with a clean version. If you inspect node_modules/plain-crypto-js after installation, you’ll see a completely innocent-looking package. But the presence of that folder is sufficient evidence that the dropper ran.


What the RAT Does

The second-stage payloads function as lightweight RATs that beacon to the C2 server every 60 seconds, transmitting system inventory and awaiting commands. All three variants implement similar capabilities: remote shell execution, binary injection, directory traversal, process listing, and system reconnaissance.

On Windows, the RAT establishes persistence via a Run key in the registry. On Linux — and this is revealing — it does not establish persistence: Huntress researchers interpret this as evidence that the attacker understands Linux targets are primarily CI/CD runners and containers, where persistence isn’t necessary because the value lies in the secrets accessible during the build.

Google Threat Intelligence Group (GTIG) attributed the attack to a North Korean actor tracked as UNC1069, noting that North Korean hackers have deep experience in supply chain attacks, which they’ve historically used to steal cryptocurrency.


How to Know If You Were Affected

Check your lockfile:

# package-lock.json
grep -E '"axios"' package-lock.json | grep -E '1\.14\.1|0\.30\.4'

# yarn.lock
grep -E 'axios@' yarn.lock | grep -E '1\.14\.1|0\.30\.4'

# Search for the malicious dependency directly
npm ls plain-crypto-js
find node_modules -name "plain-crypto-js" -type d

Look for RAT artifacts on the system:

  • macOS: /Library/Caches/com.apple.act.mond
  • Windows: %PROGRAMDATA%\wt.exe
  • Linux: /tmp/ld.py

If your lockfile was committed before the malicious versions were published and your installation didn’t update it, you weren’t affected.


What to Do If You’re Compromised

If RAT artifacts are found: treat the system as completely compromised. Don’t attempt to clean it in place — rebuild from a known safe state.

Rotate all secrets accessible from the affected system: npm tokens, SSH keys, cloud credentials (AWS, GCP, Azure), API keys, and any values in .env files accessible at the time of installation. Audit your CI/CD pipelines to identify which runs installed the affected versions — the exposure isn’t limited to development machines.

For general mitigation: downgrade to axios@1.14.0 or axios@0.30.3, remove node_modules/plain-crypto-js, and reinstall with npm install --ignore-scripts.


This incident follows a pattern that’s been accelerating in 2026: compromised maintainer accounts used to publish poisoned versions of high-trust packages. It’s not the first and won’t be the last. The question isn’t whether your dependency ecosystem is a viable attack vector — it clearly is. The question is what controls you have in place to detect it when it happens.


Sources: StepSecurity · Snyk · Wiz · Huntress · Socket · Help Net Security

1 Like