Skip to content

Axios (2026)

The Lesson: Version range wildcards don't update your package — they hand the decision to whoever publishes next. When that's a North Korean state actor who social-engineered their way into the maintainer's npm account, ^1.14.0 means "automatically install whatever they push."

The Most-Downloaded Attack Vector

Axios gets downloaded around 70 million times a week. Most of those projects use ^1.14.0 — they'd take the latest minor release automatically. On March 31, 2026, the latest minor release installed a remote access trojan. For three hours, every npm install against an affected version range ran attacker code. CI pipelines. Developer laptops. Cloud build environments. All of them.


What Happened

On March 31, 2026, two malicious versions of the Axios npm package were published: 1.14.1 and 0.30.4.1 Axios is the most widely-used JavaScript HTTP library in the ecosystem — around 70 million weekly downloads on 1.x alone.

The attacker wasn't improvising. Before touching Axios, they published plain-crypto-js@4.2.0 — a clean, functional cryptography utility — and let it sit. When they published the malicious Axios versions, plain-crypto-js@4.2.1 arrived as a new runtime dependency. Version 4.2.1 was the one with the postinstall hook.

Neither the Axios source code nor its visible dependencies appeared to change. The attack surface was the new indirect dependency. Nobody audits a new transitive dependency in an npm patch update unless they're already running something like socket.dev or a full SBOM check.

The Chain

The path in wasn't a vulnerability — it was a person.

UNC1069, a North Korean state actor with history targeting cryptocurrency and finance infrastructure, approached the Axios maintainer under the guise of a founder at a legitimate, well-known company.2 The social engineering was targeted — not a mass phishing campaign, but a tailored approach. The maintainer described it as crafted "specifically to me."

Once the account was compromised, the attacker changed the registered email address. npm's account recovery flows assume the registered email is accessible. With that changed, the real maintainer was locked out while the attacker published.

The attack unfolded in stages:

  1. plain-crypto-js@4.2.0 — functional, builds credibility in the registry
  2. axios@1.14.1 added plain-crypto-js as a runtime dependency — looks like a legitimate utility addition
  3. plain-crypto-js@4.2.1 — contains a postinstall hook that executes setup.js

The postinstall hook runs during npm install. You don't have to import the package. You don't have to call any function. Installation triggers execution.

What Was Exposed

Every developer machine, CI runner, and cloud build environment that ran npm install against an affected version range during those three hours ran attacker code. The payload was OS-specific:

Windows: VBScript dropper creating a PowerShell RAT, persisted via registry run key at HKCU:\Software\Microsoft\Windows\CurrentVersion\Run\MicrosoftUpdate

macOS: Binary dropped to /Library/Caches/com.apple.act.mond

Linux: Python payload written to /tmp and executed in background

All three variants connected to a C2 server at sfrclak[.]com:8000/6202033, sending platform identifiers to receive stage-two payloads.1 The malware deleted itself after installation — removing forensic evidence from machines that were already compromised.

The Response

StepSecurity detected the attack and the malicious versions were pulled from npm in approximately three hours.3 The maintainer publicly confirmed the social engineering campaign.

Safe versions: 1.14.0 and 0.30.3.

Security advisories recommended:

  • Downgrade immediately to a safe version
  • Audit for plain-crypto-js in node_modules
  • Assume compromise on any system that ran the affected install — absent evidence isn't safe evidence when the payload self-destructs
  • Rotate all secrets and credentials from affected environments
  • Check CI logs for connections to 142.11.206[.]73:8000

The "assume compromise" guidance is the important one. Because the payload deletes itself, a post-hoc scan that finds nothing doesn't mean nothing happened. Any system in the exposure window should be treated as potentially backdoored.

Why It Mattered

Version ranges auto-install attacker code.

// Your package.json
{ "dependencies": { "axios": "^1.14.0" } }
# What happened when you ran npm install on March 31
> plain-crypto-js@4.2.1 postinstall
> node setup.js   ← attacker code, running on your machine

The ^ prefix means "compatible with 1.14.0 — take the latest minor or patch." On March 31, that was 1.14.1. A locked package-lock.json with an exact version would have held at 1.14.0. Many CI pipelines regenerate lock files on each run or use npm install without --frozen-lockfile. Those pipelines auto-upgraded.

// Vulnerable — any future "compatible" release
{ "dependencies": { "axios": "^1.14.0" } }

// Protected — locked to exactly this version
{ "dependencies": { "axios": "1.14.0" } }

And the lock file has to hold:

# npm honors the lock file
npm ci            # fails if lock file doesn't match package.json

# This does not
npm install       # may update the lock file if ranges are satisfied by newer versions

postinstall hooks are arbitrary code execution.

This isn't a design flaw — it's a feature. Build tools, native bindings, and code generators use postinstall hooks legitimately. But npm install has always been an instruction to run arbitrary code from the internet on your machine. The implicit contract is that the publisher is trustworthy. The Axios attack didn't break the contract — it broke the assumption.

State-sponsored attacks use developer infrastructure as a delivery mechanism.

UNC1069 isn't targeting Axios. They're targeting the cryptocurrency exchanges, trading platforms, and financial services firms whose developers use Axios — the same developers whose CI runners hold AWS credentials, API keys, private key material, and database connection strings. The supply chain is how you reach those targets at scale without attacking each one individually.

Three hours was enough.

The malicious versions were live for approximately three hours. In a world where CI pipelines trigger automatically on every push, merge, and schedule — three hours propagates through thousands of build environments. Your exposure window isn't measured by when you noticed. It's measured by how many times your pipelines ran.

The Broader Pattern

The Axios attack follows the same template as event-stream — account takeover, malicious dependency injection, broad blast radius through transitive trust. The differences are of degree and intent:

event-stream (2018) Axios (2026)
Initial access Maintainer voluntarily transferred ownership Targeted social engineering by state actor
Scale ~2M weekly downloads ~70M weekly downloads
Payload Bitcoin wallet theft Full RAT, stage-two payload delivery
Dwell time Months before discovery ~3 hours
Attribution Individual actor North Korean state (UNC1069 / Sapphire Sleet)

The shorter dwell time in 2026 reflects better detection tooling. StepSecurity caught it in hours rather than months. The larger scale and more sophisticated payload reflect eight years of supply chain attack evolution.

The same attack worked in 2018 and 2026. That's not a coincidence — it's a stable pattern. The entry point is maintainer account access. The mechanism is a dependency with a postinstall hook. The blast radius is everyone downstream. Tools got better at detection; the underlying vulnerability never changed.

The Familiar Mistake

I've watched the ^ prefix cause this problem since npm was young. It's there for a reason — automatic patch updates are genuinely useful, and the alternative is dependency staleness. But the mental model that "minor updates are safe" assumes the publisher is trustworthy. The moment the publisher is a North Korean threat actor who's been sitting on a compromised npm account for three days, that assumption fails.

Pin your dependencies. Lock your lock files with npm ci in CI. Audit install hooks. These aren't exotic security measures. They're the difference between running npm install and running npm install (plus whatever UNC1069 prepared for you).


Timeline

Date Event
~Mar 2026 UNC1069 social-engineers Axios maintainer; npm account email changed to attacker-controlled address
~Mar 2026 plain-crypto-js@4.2.0 published to the npm registry; builds credibility
Mar 31, 2026 plain-crypto-js@4.2.1 (malicious postinstall hook) and axios@1.14.1, axios@0.30.4 published
Mar 31, 2026 StepSecurity detects the attack; malicious versions removed within ~3 hours
Mar 31, 2026 Advisories issued; safe versions identified as 1.14.0 and 0.30.3
Apr 1, 2026 Microsoft and Google publish detailed technical analyses; UNC1069 attribution confirmed


  1. "Mitigating the Axios npm Supply Chain Compromise." Microsoft Security Blog. April 1, 2026. https://www.microsoft.com/en-us/security/blog/2026/04/01/mitigating-the-axios-npm-supply-chain-compromise/ 

  2. "North Korea-Nexus Threat Actor Compromises Widely Used Axios NPM Package in Supply Chain Attack." Google Cloud Threat Intelligence. April 2026. https://cloud.google.com/blog/topics/threat-intelligence/north-korea-threat-actor-targets-axios-npm-package 

  3. "North Korean hackers blamed for hijacking popular Axios open source project to spread malware." TechCrunch. March 31, 2026. https://techcrunch.com/2026/03/31/hacker-hijacks-axios-open-source-project-used-by-millions-to-push-malware/