The Axios npm Attack: What It Means for Every JavaScript Project

A low-poly wooden Trojan horse standing in shadow, partially illuminated by a diagonal beam of light — a visual metaphor for hidden malware delivered through a trusted package.

On March 31, attackers compromised axios — a JavaScript library downloaded roughly 100 million times a week. Here’s what happened, who’s affected, and what to do now.

If you’ve never heard of axios, here’s the short version: it’s the library that most JavaScript applications use to talk to the internet.

Fetching data from an API, submitting a form, making a request to a backend service – axios handles it. It’s in frontend apps, backend services, CI pipelines, and internal tools. Chances are it’s somewhere in your stack right now, possibly several places.

On March 31, 2026, axios—with roughly 100 million weekly downloads—became the vector for one of the most significant npm supply chain attacks in recent memory.

Two malicious versions of axios were published to npm: axios@1.14.1 and axios@0.30.4. Both contained a hidden dependency designed to install a cross-platform remote access trojan on any developer machine that ran npm install. The window was under three hours — but given axios’s scale, that was enough. If your team ships JavaScript and installed either version during that period, treat the affected machine as compromised.

You don’t need to have installed axios directly to be at risk.

Any package in your dependency tree that lists axios with a floating version range (^1.x) and was rebuilt during the exposure window may have pulled in the malicious version automatically. This also includes AI coding assistants and automated tooling — anything that ran npm install on your behalf yesterday should be treated the same as a manual install.

We’ve written before about software supply chain security and the systemic risks that come with modern dependency management. This attack is exactly the scenario we described – not a theoretical edge case, but a live incident affecting one of the most widely used libraries in the JavaScript ecosystem.

Google’s Threat Intelligence Group has attributed the attack to UNC1069, a North Korean group previously active in cryptocurrency theft.

Here’s what happened, how it worked, and what you should check right now.

What happened

The attacker didn’t touch a single line of axios source code.

Instead, they compromised a long-lived npm access token belonging to jasonsaayman, the project’s lead maintainer. With that token, they published two new releases – one for the 1.x branch and one for the legacy 0.x branch – 39 minutes apart, covering both release lines simultaneously.

Both releases modified exactly one file: package.json. The only substantive change was adding plain-crypto-js@4.2.1 as a runtime dependency. That package was pre-staged 18 hours earlier, under a separate attacker-controlled account, with a clean version first to build registry history before the malicious update was pushed.

Why this matters: When you run npm install, you’re not just downloading the package you asked for — you’re downloading everything it depends on, including any setup scripts those dependencies declare. The attacker’s package declared one. Most developers never see this happening. It runs silently, by design. By the time npm install finished, the script had already executed, phoned home, and delivered its payload.

plain-crypto-js contains a full copy of the legitimate crypto-js library – every source file identical, bit-for-bit. The only difference is a postinstall hook: “node setup.js”.

When npm resolves the dependency tree and runs that hook, the dropper fires. It contacts the attacker’s command-and-control server, delivers a platform-specific payload for macOS, Windows, or Linux, then deletes itself and replaces package.json with a clean stub reporting version 4.2.0.

By the time npm install finishes, there’s no error, no warning, no obvious trace. The directory node_modules/plain-crypto-js/ exists, but npm list shows version 4.2.0 – not the malicious 4.2.1 that actually ran. Standard npm audit finds nothing.

Why this specific attack is worth studying

Most supply chain incidents involve obvious red flags – a zero-history package, a suspicious name, a sudden maintainer change.

This one was deliberately engineered to avoid all of them.

Put plainly: most security tools work by recognising known bad things – a flagged domain, a suspicious file, a package with no history. This attack had none of those signals. It arrived under a trusted name, from a legitimate account, with clean source code and a registry history. The tools that were supposed to catch it passed it through.

HRVOJE FILAKOVIC, CYBERSECURITY ENGINEER

That’s what makes it worth paying attention to, even if axios isn’t in your stack – the technique will be reused.

The attacker published a clean decoy package 18 hours before activating the payload – long enough to avoid “brand new account” alerts from registry scanners. The malicious axios releases were signed by the legitimate maintainer’s account. No corresponding commit or tag appeared on GitHub (that gap is the forensic signal, in hindsight), but most CI systems don’t verify OIDC provenance on pull.

The plain-crypto-js package was designed to survive a human code review. The library files were identical to the legitimate crypto-js. A developer diffing the package against its stated source would find nothing. The malicious payload lived in package.json and setup.js – a postinstall script that looks, at a glance, like a standard build step.

This is the attack pattern that NIS2 and CRA regulations are increasingly focused on: not a breach of your perimeter, but a compromise of the supply chain your code depends on.

Your code didn’t have a vulnerability. Your tooling did.

The OIDC misconfiguration that made it possible

Axios had OIDC Trusted Publishing configured for its release workflow.

In theory, this should have made a token-based publish impossible – OIDC ties releases to specific GitHub Actions runs, and the ephemeral token can’t be stolen.

In practice, the GitHub Actions workflow passed both the OIDC credentials and a classic NPM_TOKEN environment variable. When both are present, npm defaults to the token. The long-lived token – which can be exfiltrated – was effectively the only authentication method that mattered.

This is a common misconfiguration. Many projects enable OIDC Trusted Publishing and consider the job done, without removing or rotating the classic token that overrides it.

Check if you’re affected – right now

Step 1 – Check your lockfile for the malicious versions

grep -E '"axios"' package-lock.json | grep -E "1\.14\.1|0\.30\.4"
npm list axios 2>/dev/null | grep -E "1\.14\.1|0\.30\.4"

Step 2 – Check for the malicious dependency in node_modules

The presence of this directory – regardless of what version package.json now reports – means the dropper executed.

ls node_modules/plain-crypto-js 2>/dev/null && echo "DROPPER RAN"

Step 3 – Check for persistent artifacts

# macOS
ls -la /Library/Caches/com.apple.act.mond 2>/dev/null && echo "COMPROMISED"


# Linux
ls -la /tmp/ld.py 2>/dev/null && echo "COMPROMISED"


# Windows (cmd.exe)
dir "%PROGRAMDATA%\wt.exe" 2>nul && echo COMPROMISED

If you find any of these

The response depends on where the install ran.

For ephemeral CI runners (e.g. GitHub-hosted), the runner is destroyed after each job — rotate any secrets that were injected during the affected run and move on.

For developer machines and self-hosted runners, treat the system as fully compromised: isolate it from the network immediately and re-image it or restore from a verified clean backup taken before March 30.

Do not attempt to clean in place — the RAT deploys persistence mechanisms that survive a reboot, so credential rotation on a live system is not sufficient.

Once you have a clean machine, rotate everything that was accessible from it: npm tokens, SSH keys, cloud credentials (AWS, GCP, Azure), CI/CD secrets, and any values in .env files present at install time.

To downgrade cleanly

npm install axios@1.14.0  # for 1.x users
npm install axios@0.30.3  # for 0.x users

What to change in your CI/CD configuration

Beyond the immediate incident, this attack exposes a few controls worth auditing across your pipelines.

  • Remove or rotate long-lived npm tokens. If your publish workflow uses a classic NPM_TOKEN alongside OIDC, the token wins. Either remove it from the workflow entirely, or rotate it and restrict it to the minimum necessary scope.
  • Add –ignore-scripts to CI installs. This prevents postinstall hooks from running during automated builds:
npm ci --ignore-scripts
  • Pin versions explicitly. Avoid floating ranges like ^1.14.0. Both malicious releases were tagged latest, so any unpinned install resolved to them.
  • Add provenance verification to your review process. For major releases of critical packages, check npm registry metadata for OIDC provenance. Legitimate axios 1.x releases show GitHub Actions as the publisher with a trustedPublisher field. The malicious release showed the maintainer’s username directly – no OIDC binding, no corresponding GitHub tag.
  • Block the C2 domain at the network level. If you have a firewall or DNS filtering in place, block the C2 domain sfrclak[.]com and IP address 142[.]11[.]206[.]73 on port 8000. Flag this to your network or DevOps team rather than handling it at the host level — a firewall rule covers all machines rather than requiring per-device changes.

The broader pattern

This isn’t an isolated incident.

The axios attack follows the same playbook as the CrowdStrike npm compromise, the IoliteLabs VSCode extension backdoor from a few days earlier, and dozens of similar incidents over the past two years.

The package manager ecosystem runs on implicit trust: if a package is in npm under a recognizable name and a legitimate maintainer’s account, most tooling and most developers treat it as safe.

That model is under sustained attack.

The attacker here invested 18 hours of prep time, built platform-specific payloads for three operating systems, and designed the dropper to self-destruct. This is not someone experimenting – it’s operational tradecraft applied to the JavaScript supply chain.

As we covered in our supply chain security framework, the highest-risk entry points are often not your own code but the tools and processes you depend on to build and deploy it.

The question isn’t whether your perimeter is secure, it’s whether your CI pipeline would have caught this before it ran.

For teams with third-party risk exposure

If you’re managing a product that runs JavaScript in CI and you have compliance obligations – PCI DSS, NIS2, ISO 27001 – this incident is worth documenting even if you weren’t affected.

Our third-party cyber risk management work often starts with incidents like this one: not after a breach, but as a trigger to audit what dependency hygiene actually looks like in practice across an engineering org.

The controls that would have caught this – OIDC provenance checks, version pinning, –ignore-scripts in CI, outbound network monitoring – aren’t difficult to implement. They just tend not to exist until something goes wrong.

If you want to review your current posture, get in touch.

Indicators of compromise

Malicious packages
Malicious packageaxios@1.14.1 (shasum: 2553649f)
Malicious packageaxios@0.30.4 (shasum: d6f3f62f)
Malicious dependencyplain-crypto-js@4.2.1
Attacker npm accountjasonsaayman (email changed to ifstap[at]proton[.]me)
Staging npm accountnrwise (email: nrwise[at]proton[.]me)
Network indicators
C2 domainsfrclak[.]com
C2 IP142[.]11[.]206[.]73
C2 URLhxxp://sfrclak[.]com:8000/6202033
C2 port8000
macOS POST bodypackages.npm[.]org/product0
Windows POST bodypackages.npm[.]org/product1
Linux POST bodypackages.npm[.]org/product2
Filesystem artifacts
macOS artifact/Library/Caches/com.apple.act.mond
Windows (persistent)%PROGRAMDATA%\wt.exe
Windows temp (self-deletes)%TEMP%\6202033.vbs | %TEMP%\6202033.ps1
Linux artifact/tmp/ld.py
Advisory references
GitHub advisoryGHSA-fw8c-xr5c-95f9
Malware advisoryMAL-2026-2306
Malware family (GTIG)WAVESHAPER.V2
Safe versions
Safe 1.x versionaxios@1.14.0 (shasum: 7c29f4cf)
Safe 0.x versionaxios@0.30.3
Infinum’s cybersecurity team provides penetration testing, third-party risk management, and secure development advisory for enterprise and regulated-industry clients. Learn more at infinum.com/cybersecurity.