The Axios npm Supply Chain Attack

Updated 5 Oct 2026 · Incident date 31 Mar 2026 · npm

Packageaxios 1.14.0 -> 1.14.1 and axios 0.30.3 -> 0.30.4
Filepackage.json

Axios 1.14.1 and axios 0.30.4 on npm were malicious. An attacker published both on 31 March 2026 with the stolen npm account of the lead maintainer. Each version added one new dependency, plain-crypto-js 4.2.1, which installs a remote access trojan (RAT) during npm install.

The axios code itself did not change. Only package.json changed. npm removed both versions about three hours later, but any machine or CI job that installed them in that window can still be infected. This page lists the facts from the incident reports, the files to look for, and the commands to check. It also covers the question many people ask: is this CVE-2026-40175? It is not. For the wider pattern, read our guide to npm supply chain attacks.

How the attack unfolded

The attacker took over the npm account of the axios maintainer (jasonsaayman), prepared a fake dependency, and published two poisoned axios releases in 39 minutes. Endor Labs and StepSecurity give the same order of events. All times are UTC.

TimeEvent
30 Mar, 05:57plain-crypto-js 4.2.0 is published. It is a clean copy of a real library. It builds a publishing history for the new package.
30 Mar, 16:03The domain sfrclak.com is registered. It becomes the command server.
30 Mar, 23:59plain-crypto-js 4.2.1 is published with a postinstall hook.
31 Mar, 00:21axios 1.14.1 is published with the maintainer account and tagged latest.
31 Mar, 01:00axios 0.30.4 is published on the legacy branch.
31 Mar, about 03:00npm removes the bad versions. plain-crypto-js is replaced with a security placeholder.

The attacker bypassed the project's normal release path. StepSecurity reports that the releases came from stolen npm credentials and not from the GitHub Actions pipeline. Huntress saw the first infected Mac 89 seconds after the 1.14.1 publish. It saw more than 135 endpoints among its partners contact the command server during the three-hour window.

Axios has more than 400 million monthly downloads and 174,000 direct dependents, according to Endor Labs. A project that used a caret range such as ^1.x.x without a lockfile resolved to 1.14.1 on a fresh install during the window.

Huntress later added attribution. It reports that Google Threat Intelligence Group linked the attack to UNC1069, a suspected North Korean group, and that Elastic Security Labs found overlap between the macOS binary and a backdoor linked to North Korea.

Which axios versions were affected

Two axios versions were malicious: 1.14.1 and 0.30.4. The last clean versions are 1.14.0 and 0.30.3.

PackageVersionStatus
axios1.14.1Malicious. Tagged latest. Exposed about 3 hours 30 minutes.
axios0.30.4Malicious. Tagged legacy. Exposed about 2 hours 51 minutes.
plain-crypto-js4.2.1Malicious dependency. Runs the dropper.
plain-crypto-js4.2.0Clean decoy. Published first to build history.
axios1.14.0 and 0.30.3Clean. Safe to pin.

npm has removed the bad versions, so a new install cannot fetch them. A lockfile, a cache, a Docker layer or a build artifact from 31 March can still hold them. Check those too.

What plain-crypto-js did

The package ran a script named setup.js at install time and dropped a remote access trojan for the operating system it found. No axios code imports plain-crypto-js. The package existed only to run that hook. StepSecurity found that exactly one file differed between clean and poisoned axios: package.json.

The dropper contacted sfrclak.com within about two seconds of the install start, before npm finished resolving other dependencies. Then it hid its tracks. It deleted setup.js, deleted the package.json that held the hook, and renamed a clean stub (package.md) to package.json. After an infection, the manifest in node_modules/plain-crypto-js looks normal. The folder itself is the sign.

All three RATs share four commands: kill, runscript, peinject and rundir. They run scripts, load code in memory and list directories. They beacon to the server every 60 seconds. Endor Labs reports that the first Windows run sent about 33 KB of directory listings and 7 KB of system data. A RAT gives the operator the same access as the logged-in user, so every secret on that machine is at risk.

Indicators of compromise

The indicators below come from Huntress and Endor Labs.

How to check

Look for the bad axios version and for the plain-crypto-js folder in every project and every CI cache. The folder matters most because the malware cleans its own manifest. These commands only read files. They do not run the package.

npm ls axios plain-crypto-js
ls node_modules/plain-crypto-js
grep -l "plain-crypto-js" package-lock.json yarn.lock pnpm-lock.yaml 2>/dev/null

If npm ls shows axios 1.14.1 or 0.30.4, or the folder exists, treat the machine as infected. To look for the dropped files, run the line for your system.

ls -l /Library/Caches/com.apple.act.mond   # macOS
ls -l /tmp/ld.py                         # Linux

On Windows, look for %PROGRAMDATA%\wt.exe and the MicrosoftUpdate Run key. Also search your network logs for sfrclak.com or 142.11.206.73.

Do not rely on axios being absent from package.json. A transitive dependency can pull it in. npm ls axios shows the full tree.

What to do if you installed it

Treat the machine as fully compromised, rebuild it, and rotate every secret it can read. The reports from Huntress, Endor Labs and StepSecurity agree on these steps.

  1. Isolate the machine from the network.
  2. If you find any RAT file, do not clean it by hand. Rebuild from a known-good image.
  3. Rotate all credentials the machine or CI job can read: npm tokens, SSH keys, cloud keys, CI secrets, API keys and OAuth tokens.
  4. Pin axios to a clean version: npm install axios@1.14.0 or axios@0.30.3. Add an overrides entry in package.json so a transitive dependency cannot move it.
  5. Remove the bad folder and reinstall without scripts: rm -rf node_modules/plain-crypto-js && npm install --ignore-scripts. Then clear the cache with npm cache clean --force.
  6. Review CI runs that executed npm install between 31 March 00:21 and 03:25 UTC. Rotate the secrets those runs held.
  7. Block sfrclak.com and 142.11.206.73 at the firewall or DNS.

To lower the risk next time, commit lockfiles and use npm ci in CI. Set npm config set min-release-age 3 to delay brand-new versions. Use --ignore-scripts where a build does not need install hooks. Huntress and Endor Labs recommend all three. The same group of ideas applies to the Trivy and LiteLLM incidents, see the Trivy attack and the LiteLLM attack.

Is this CVE-2026-40175?

No. CVE-2026-40175 is a separate axios bug, and it has no link to the March 2026 malicious releases. The GitLab advisory for CVE-2026-40175 (GHSA-fvcv-3m26-pcqx) is titled "Axios has Unrestricted Cloud Metadata Exfiltration via Header Injection Chain". It was published on 10 April 2026, ten days after the attack. It does not mention plain-crypto-js or any malicious release.

The flaw is a gadget chain. If a different package in your app already allows prototype pollution, an attacker can use axios to write unsanitized header values into outbound requests. Carriage-return and line-feed characters in those values can split or smuggle requests. The advisory rates it CVSS 4.8, moderate. It affects axios 1.0.0 up to 1.14.x and all versions before 0.31.0. The fixed versions are 1.15.0 and 0.31.0.

So there are two different things to check. The malicious versions 1.14.1 and 0.30.4 are a supply chain compromise and have no CVE in the Endor Labs write-up. CVE-2026-40175 is a code flaw that a normal upgrade to 1.15.0 or 0.31.0 fixes. Upgrading to 1.15.0 does not remove an infection that already happened. If you ran 1.14.1 or 0.30.4, follow the steps above.

What Vigilance showed

Vigilance compares the version you trust with the new one and names the file that gained a new capability. The block below is rebuilt from the public reports in the words Vigilance prints. It is not a captured scan, because the malicious release is not redistributed.

vigi diff --old axios-1.14.0 --new axios-1.14.1
files scanned: 80

HEADS UP  1 file can now do things the old version could not. The rest changed and gained nothing.

CHANGED    package.json
           It now runs a command on its own when it is installed, downloads from the internet and runs other programs. It did not before.

Frequently asked questions

What happened to axios on npm?

On 31 March 2026 an attacker used a stolen maintainer account to publish axios 1.14.1 and 0.30.4. Both added the dependency plain-crypto-js 4.2.1, which installs a remote access trojan at install time. npm removed the versions about three hours later.

Which axios versions are safe?

Axios 1.14.0 and 0.30.3 are the last clean versions before the attack. Versions 1.14.1 and 0.30.4 are malicious. Pin a clean version and add an overrides entry so a transitive dependency cannot change it.

How do I know if I installed the malicious axios?

Run npm ls axios plain-crypto-js and check whether the folder node_modules/plain-crypto-js exists. The malware rewrites its own manifest, so the folder is the reliable sign. Also check lockfiles, CI caches and the dropped RAT files for your operating system.

Is axios 1.14.1 safe to use?

No. Axios 1.14.1 is a malicious release and npm has removed it. Do not use it. Install 1.14.0 or a later release that your own review trusts.

Is CVE-2026-40175 the axios supply chain attack?

No. CVE-2026-40175 is a separate header injection flaw in axios, fixed in 1.15.0 and 0.31.0. The malicious releases 1.14.1 and 0.30.4 are a supply chain compromise and have no link to that CVE.

Sources

  1. huntress.com/blog/supply-chain-compromise-axios-npm-package
  2. endorlabs.com/learn/npm-axios-compromise
  3. stepsecurity.io/blog/axios-compromised-on-npm-malicious-versions-drop-remote-access-trojan
  4. advisories.gitlab.com/npm/axios/CVE-2026-40175/

More supply chain attacks

All 111 attacks in the library · npm supply chain attacks · How to prevent supply chain attacks

Check the next update before you install it

Vigilance compares the version you trust with the new one. It names the one file that can now do something it could not do before.

Start Free