TLDR: On March 31, 2026, between 00:21 and 03:29 UTC, two malicious versions of Axios —
1.14.1and0.30.4— were published to npm via a compromised maintainer account. They silently installed a cross-platform remote access trojan (RAT) on any machine that rannpm installduring that window. The malware targeted macOS, Windows, and Linux, contacted a live command-and-control server, self-deleted its own traces after execution, and established persistence. Axios has 83 million weekly downloads. If your CI/CD pipeline ran without a pinned version during those three hours, check your system now.
The Package Everyone Trusts
If you've written JavaScript in the last decade — frontend or backend — you've almost certainly used Axios. It's the HTTP client. The one that just works. It sits in millions of package.json files across the world as a dependency so standard it's rarely thought about.
Which is exactly why it was targeted.
On the night of March 30–31, 2026, an attacker who had obtained the npm credentials of Axios's primary maintainer — @jasonsaayman — used them to publish two poisoned versions directly to the npm registry, bypassing the project's GitHub Actions CI/CD pipeline entirely. The malicious versions were live for just over three hours. In those three hours, any automated build system, developer machine, or container that pulled a fresh Axios install without a pinned version could have been fully compromised.
The attack was not opportunistic. It was planned, staged, and executed with remarkable precision.
How It Was Built — 18 Hours in Advance
The attacker's playbook reveals serious operational sophistication. They didn't rush.
At 05:57 UTC on March 30, they published plain-crypto-js@4.2.0 to npm — a clean, harmless package with no malicious content. Just establishing a footprint. Creating a brief package history to reduce suspicion.
Nearly 18 hours later, at 23:59 UTC, they published plain-crypto-js@4.2.1 — the same package name, now containing the malicious payload.
Then, at 00:21 UTC on March 31, they published axios@1.14.1 using the compromised @jasonsaayman account. The only change to Axios? A single line adding plain-crypto-js@4.2.1 as a runtime dependency — a package that Axios's own source code never imports anywhere, added solely to trigger its postinstall hook: node setup.js.
At 01:00 UTC, a second poisoned release — axios@0.30.4 — followed, hitting the legacy version branch. Both release branches compromised within 39 minutes.
npm quarantined both versions at 03:29 UTC. 188 minutes total exposure.
What Happened When You Ran npm install
The setup.js postinstall dropper used double-layer obfuscation — reversed Base64 encoding combined with an XOR cipher keyed to OrDeR_7077 — to evade static analysis tools. Once decoded, it detected the host operating system and reached out to sfrclak[.]com:8000 (IP: 142.11.206.73) to download a platform-appropriate second-stage payload.
On macOS: An AppleScript downloaded a C++ RAT binary to /Library/Caches/com.apple.act.mond — deliberately mimicking Apple's own background daemon naming convention. Once running, it fingerprinted the system, generated a unique victim ID, and beaconed to the C2 server every 60 seconds using a fake Internet Explorer 8 User-Agent string. The attacker could send arbitrary shell commands, execute additional payloads, or enumerate the filesystem on demand.
On Windows: A VBScript downloader copied PowerShell to %PROGRAMDATA%\wt.exe — disguising it as Windows Terminal — and executed a hidden PowerShell RAT that connected to the same C2 server.
On Linux: A Python RAT was downloaded to /tmp/ld.py and launched as an orphaned background process via nohup python3, detaching it from the terminal session that spawned it.
After launching the RAT, the dropper performed forensic self-cleanup: it deleted setup.js, removed the package.json containing the postinstall hook, and replaced it with a clean package.md file renamed to package.json. If you inspected node_modules/plain-crypto-js after the fact, you would find no obvious signs a postinstall script had ever run.
As StepSecurity noted in their analysis: "Neither malicious version contains a single line of malicious code inside Axios itself." The attack was entirely in the injected dependency.
Why Your Lockfile Is Your First Line of Defence
Here's the critical question: were you affected?
The three-hour window (00:21–03:29 UTC) is the key constraint. If your package-lock.json or yarn.lock was committed before the malicious versions were published and your install ran npm ci — which strictly uses the lockfile — you were not affected. The lockfile would have pinned you to a prior, clean Axios version.
Risk was highest for:
-
CI/CD pipelines running on a schedule or on commit that use
npm installwithout enforcing the lockfile, especially those running during early UTC hours -
Developers who ran
npm installornpm updateduring the window on a machine that resolved the new versions -
Projects depending on
@qqbrowser/openclaw-qbot@0.0.130or@shadanai/openclawversions2026.3.31-1and2026.3.31-2— two additional packages that shipped the same maliciousplain-crypto-jsdependency, with no dependency on the time window
This is the same attack pattern we wrote about with LiteLLM just a week ago — and before that, XZ Utils. The attack surface is different; the playbook is identical: compromise a trusted publishing credential, inject a malicious dependency, rely on the ecosystem's implicit trust.
Check If You Were Affected — Right Now
Step 1: Check your lockfile for the affected versions
# npm
grep -E '"axios"' package-lock.json | grep -E '1\.14\.1|0\.30\.4'
# yarn
grep 'axios@' yarn.lock | grep -E '1\.14\.1|0\.30\.4'
Step 2: Check for the malicious dependency
npm ls plain-crypto-js
# or
find node_modules -name "plain-crypto-js" -type d
Step 3: Check for RAT artifacts on potentially affected machines
| Platform | Indicator of Compromise |
|---|---|
| macOS | /Library/Caches/com.apple.act.mond |
| Windows | %PROGRAMDATA%\wt.exe |
| Linux | /tmp/ld.py |
| Network | Outbound traffic to sfrclak[.]com or 142.11.206.73:8000
|
If you find any of these, stop. The RAT was active and beaconing. Do not attempt to clean the system in place.
What to Do If You Were Affected
Isolate the machine immediately. If a RAT was running, the attacker had arbitrary code execution. Do not continue using the system for anything sensitive.
Rotate every credential on that machine. API keys, npm tokens, GitHub tokens, SSH keys, AWS credentials, cloud service accounts, database passwords, .env file contents. Everything. Rotate from a clean device, not the compromised one.
Audit your CI/CD pipeline logs for the March 31 UTC window. Determine exactly which builds installed the affected versions and what those build environments had access to.
Rebuild compromised environments from a known-clean snapshot. Do not attempt to remediate in place. The dropper self-deleted, but the RAT and its persistence mechanism may have installed additional payloads.
Downgrade Axios to version 1.14.0 or 0.30.3 and pin it explicitly in your package.json. Block egress traffic to sfrclak[.]com at your network perimeter.
The Structural Change That Would Have Stopped This
Two controls that were widely recommended but not universally adopted would have prevented compromise even during the three-hour window.
Use npm ci in CI/CD, never npm install. npm ci enforces strict lockfile compliance. It installs exactly the versions in your lockfile and fails if package.json and the lockfile are out of sync. An attacker publishing a new version to the registry cannot affect a build that never consults the registry for versions — it only reads from the lockfile.
Use --ignore-scripts for automated installs. Running npm ci --ignore-scripts prevents postinstall hooks from executing entirely. The entire Axios attack was delivered through a postinstall hook. This flag would have blocked it completely — though be aware it can break packages that legitimately require native compilation during install.
These aren't exotic security measures. They're npm flags. The fact that so many pipelines don't use them by default is part of why supply chain attacks through postinstall scripts remain so effective.
The Pattern We're Now Watching Every Week
The Axios attack came one week after the LiteLLM compromise — which itself came from credentials stolen during the Trivy breach. These attacks are cascading. Each compromised tool provides credentials or access that enables the next attack. The software supply chain is now OWASP's #3 risk category specifically because this pattern is accelerating, not slowing down.
If your organisation uses open source at any scale — and virtually every organisation does — your dependency tree is an attack surface that nobody on your team has fully reviewed. The question isn't whether one of those packages will be compromised. It's whether you'll know about it within three hours or three months.
At Kuboid Secure Layer, our security assessments include supply chain exposure analysis — dependency tree auditing, CI/CD pipeline security, and secrets management review. If you want to understand what your dependency graph actually looks like from an attacker's perspective, let's talk.
Are you running Axios in production? Did you check your lockfile after this news broke? Drop a comment — and if you found the affected versions in your environment, what did your response look like? The more we share, the better prepared the community gets.
Top comments (0)