Axios npm Package Compromised : The Attack at a Glance

ACTIVE THREAT · SUPPLY CHAIN ATTACK · NORTH KOREA APT

TL;DR — IMMEDIATE ACTION REQUIRED

If you installed [email protected] or [email protected], assume full system compromise. Roll back to [email protected] or [email protected] immediately, rotate every credential on that machine, and check your network logs for connections to sfrclak[.]com or 142.11.206[.]72:8000

100M+

WEEKLY DOWNLOADS

<3 hrs

WINDOW LIVE ON NPM

3 OS

PLATFORMS TARGETED

18 hrs

PRE-STAGED PLANNING

Axios is the kind of package that nobody thinks about anymore — and that's exactly the point. Over 100 million developers, CI pipelines, and production servers pull it down every week without a second thought. It just works. It's been around since 2014. The maintainer is a known, real person with a commit history stretching back years.

That trust — baked deep into the muscle memory of the JavaScript ecosystem — is precisely what a North Korean APT exploited on the night of March 30, 2026. The attack didn't touch a single line of Axios source code. Instead, it weaponised the package's own dependency resolver, using npm's own lifecycle hooks to detonate a cross-platform Remote Access Trojan on every machine that ran npm install during a two-hour window.

The attacker's first move wasn't the malicious package — it was patience. Nearly 18 hours before the poisoned Axios releases appeared on npm, a "clean" decoy package named [email protected] was quietly published to the registry. Its only purpose was to seed a brief, plausible history on npm — enough to avoid "brand-new package" detection heuristics.

Then, in a 39-minute burst starting just after midnight UTC on March 31, the operation went live. Using credentials stolen from the primary Axios maintainer's npm account, the attacker pushed two poisoned releases: [email protected] (tagged latest) and [email protected] (tagged legacy). By targeting both branches simultaneously, the blast radius covered every project that hadn't pinned to a specific minor version.

"There are zero lines of malicious code inside Axios itself. That's exactly what makes this attack so dangerous."

Attack Timeline

March 30, 2026 — 05:57 UTC

Decoy Package Seeded

[email protected] published to npm — clean, no payload. Establishes registry history to evade "new package" alerts.

March 30, 2026 — 23:59 UTC

Payload Loaded

[email protected] published containing the obfuscated dropper setup.js with postinstall hook.

March 31, 2026 — 00:21 UTC

First Poisoned Axios Release

[email protected] published via compromised jasonsaayman account — tagged latest, resolves to backdoored package on default npm install.

March 31, 2026 — 01:00 UTC

Legacy Branch Poisoned

[email protected] published — tagged legacy. Both release branches now compromised within 39 minutes of each other.

March 31, 2026 — 01:50 UTC

Disclosure Filed

Elastic Security Labs files a GitHub Security Advisory after automated supply-chain monitoring flags anomalous behaviour.

March 31, 2026 — 03:29 UTC

Malicious Versions Removed

npm registry pulls both poisoned releases. Total exposure window: approximately 3 hours and 8 minutes.

How the Attack Actually Worked: Full Technical Breakdown

Step 1 — Account Takeover

The entry point was the npm account of jasonsaayman, the lead Axios maintainer. The attacker changed the account email from the legitimate jasonsaayman@gmail[.]com to an attacker-controlled ProtonMail address: ifstap@proton[.]me. Once npm credentials are rotated to a new email, the original owner loses recovery access entirely.

A critical forensic signal that exposed this was the publishing method. Every legitimate Axios 1.x release was published through GitHub Actions using npm's OIDC Trusted Publisher mechanism — a system that cryptographically binds each publish to a verified CI/CD workflow and produces an SLSA provenance attestation. The malicious 1.14.1 was published directly from the CLI using a stolen npm access token. No OIDC binding. No SLSA provenance. No corresponding commit, tag, or release in the Axios GitHub repository. The package existed only on npm.

Step 2 — The Phantom Dependency

Rather than modifying Axios source files, the attacker made a single surgical change to package.json: adding plain-crypto-js@^4.2.1 as a runtime dependency. The real Axios has exactly three dependencies: follow-redirects, form-data, and proxy-from-env. The addition of plain-crypto-js is unambiguous tampering — but not the kind of thing most developers notice when they're not actively auditing their dependency tree.

Step 3 — The Postinstall Hook Trigger

When a developer or CI system runs npm install axios, npm resolves the full dependency tree, downloads [email protected], and executes any declared lifecycle scripts. The malicious package declared:

"scripts": {

"test": "echo \"Error: no test specified\" && exit 1",

"postinstall": "node setup.js"

}

The postinstall hook fires automatically during installation with zero user interaction required. This is a legitimate npm feature used for build steps and native compilation. The attacker simply repurposed it as a trigger.

Step 4 — The Obfuscated Dropper (SILKBELL)

The core dropper is setup.js, internally designated SILKBELL by Google's Threat Intelligence Group. It uses two layers of obfuscation to defeat static analysis:

• Reversed Base64 encoding with substituted padding characters

• XOR cipher with the key OrDeR_7077 and constant value 333

All sensitive strings — module names, platform identifiers, file paths, command templates, and C2 addresses — are reconstructed at runtime. Running the file through a standard static scanner or even a basic string search yields nothing actionable.

Step 5 — The Cross-Platform RAT (WAVESHAPER.V2)

The second-stage backdoor — called WAVESHAPER.V2 by Google GTIG — is the same RAT across all three platforms, implemented differently to suit each OS:

Windows — PowerShell

macOS — C++ binary

Linux — Python

Beacons, receives commands, executes arbitrary PowerShell

Targets Apple system paths and keychain-adjacent directories

Targets CI runners, cloud credential stores, SSH directories

All three implementations share identical C2 protocol, command set, beacon cadence, and spoofed user-agent strings — confirming they were built from a common codebase.

Step 6 — Anti-Forensic Self-Destruct

After the dropper executes, it cleans up after itself. The malicious setup.js is deleted. The package.jsoninside plain-crypto-js is replaced with a clean, innocuous copy — one that no longer contains the postinstall script. A developer who inspects their node_modules an hour after a compromised install will find no trace that anything went wrong. The compromise already happened. The RAT is already running. The evidence is already gone.

Attribution: North Korea's Fingerprints

Three major threat intelligence organisations independently converged on North Korean attribution within 24 hours:

Sophos CTU

NICKEL GLADSTONE

Identical forensic metadata, C2 patterns, and malware exclusively associated with this state-sponsored group focused on generating revenue for the North Korean regime.

Microsoft Threat Intel

Sapphire Sleet

Infrastructure overlaps with known Sapphire Sleet C2 domains, following the group's established pattern of poisoning widely adopted open-source frameworks.

Google GTIG

UNC1069

Financially motivated DPRK-nexus threat actor active since at least 2018. WAVESHAPER.V2 is an updated version of malware exclusively attributed to UNC1069 in prior campaigns.

Indicators of Compromise (IOCs)

Use the following indicators to hunt across your SIEM, EDR, and network appliances:

Indicator

Type

Description

[email protected]

npm package

Malicious — tagged latest during attack window

[email protected]

npm package

Malicious — tagged legacy during attack window

[email protected]

npm package

Malicious dropper delivery vehicle

e10b1fa84f1d6481625f741b69892780140d4e0e7769e7491e5f4d894c2e0e09

SHA256 — setup.js

SILKBELL dropper

fcb81618bb15edfdedfb638b4c08a2af9cac9ecfa551af135a8402bf980375cf

SHA256

Linux RAT (Python)

617b67a8e1210e4fc87c92d1d1da45a2f311c08d26e89b12307cf583c900d101

SHA256

Windows RAT (PowerShell)

92ff08773995ebc8d55ec4b8e1a225d0d1e51efa4ef88b8849d0071230c9645a

SHA256

macOS RAT (C++)

sfrclak[.]com

Domain — C2

Command and control server

142.11.206[.]72

IP — C2

C2 server, port 8000

142.11.206[.]73

IP — C2

Secondary C2, port 8000

ifstap@proton[.]me

Email

Attacker-controlled account used for takeover

OrDeR_7077

XOR key

Obfuscation key used in SILKBELL dropper

YARA Detection Rule — WAVESHAPER.V2

rule WAVESHAPER_V2 {

meta:

description = "Detects WAVESHAPER.V2 RAT — UNC1069/Sapphire Sleet"

author = "Google GTIG / ThreatBlock Research"

date = "2026-03-31"

platforms = "Any"

strings:

$s1 = "OrDeR_7077" ascii wide fullword

$s2 = "String.fromCharCode(S^a^333)" ascii wide

$s3 = "\"TE9DQUw^\"replaceAll(\"^\")" ascii wide

$s4 = "\"UFM_\"replaceAll(\"_\",\"=\")" ascii wide

condition:

uint16(0) != 0x5A4D

and filesize < 100KB

and 2 of ($s*)

}

Immediate Remediation Steps

If there is any chance your environment hit the affected versions, treat the system as compromised and work backwards from that assumption.

1. Pin to safe versions

npm install [email protected] # safe 1.x

npm install [email protected] # safe legacy

# Add override in package.json to block transitive resolution:

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

2. Purge plain-crypto-js entirely

rm -rf node_modules/plain-crypto-js

npm install --ignore-scripts

3. Flush npm cache

npm cache clean --force

4. Rotate every credential

Treat all secrets on a potentially affected machine as compromised: npm tokens, AWS keys, SSH keys, GitHub tokens, CI/CD secrets, .env values. Revoke and reissue — do not rotate in place on the compromised host.

5. Audit CI/CD pipeline logs

Search build logs for the March 31 UTC exposure window. Look for [email protected], [email protected], or plain-crypto-js in any npm install or npm ci output. Any pipeline that installed either version should be treated as compromised.

6. Hunt for C2 beaconing

Check network egress logs for outbound connections to sfrclak[.]com, 142.11.206.72, or 142.11.206.73 on port 8000. Add these to your DNS/firewall blocklist immediately.

7. Harden npm install policy going forward

Use npm ci --ignore-scripts in all CI pipelines. This flag prevents postinstall hooks from firing during automated builds — the exact mechanism this attack relied on.

8. Disable or restrict automated dependency bots

Dependabot and Renovate can automatically merge dependency updates — exactly the kind of automation that would have silently upgraded to the malicious version and deployed it to production without human review.

Key Takeaways for Security Teams

• Popularity is not safety. 100 million weekly downloads made Axios a more attractive target, not a safer one.

• Source code integrity does not equal dependency integrity. The Axios source was clean. The attack lived entirely in the dependency tree.

• Postinstall hooks are an arbitrary code execution surface. npm ci --ignore-scripts in CI is not optional anymore.

• Ephemeral runners help, but secrets injected during the exposure window are still compromised. Rotate them regardless.

• Lockfiles work — but only if you use npm ci, not npm install.

• Account takeover bypasses every code-level supply chain control. MFA on maintainer accounts is non-negotiable.

• SLSA provenance and Trusted Publisher binding are detectable defences — use tooling that verifies them.

The good news — if there is any — is that the attack was detected within hours, the malicious versions were live for under three hours, and the community response was swift. The IOCs are well documented. The attribution is strong. If you run the remediation steps above and you weren't in the exposure window, you're fine.

But the next one might not be detected so fast. And it won't target a package you've never heard of.

Share this post

Loading...