On March 31, 2026, the axios npm package — with over 100 million weekly downloads — was compromised and used to distribute malware.
A threat actor took over the lead maintainer's npm account, published two backdoored versions (1.14.1 and 0.30.4), and added a hidden dependency that deployed a cross-platform remote access trojan. The payload targeted Windows, macOS, and Linux. The malicious versions were live for only about three hours before they were removed.
In practice, three hours was enough.
Microsoft attributed the attack to Sapphire Sleet, a North Korean state actor. Google's Threat Intelligence Group confirmed UNC1069 involvement. This was a coordinated, pre-staged operation — the malicious dependency was planted 18 hours before activation.
Why This Matters to You
If your package.json uses caret ranges like ^1.x, a routine npm install could have pulled the compromised version automatically. No unusual action required. Just your normal CI/CD pipeline doing what it was designed to do.
Most teams would not have caught this in time.
Not because they're careless, but because the tooling gap is real:
-
npm auditlooks for known CVEs. This wasn't a CVE when it hit. - Dependabot follows published advisories. This version came from the real maintainer account.
- Lockfiles help, but only if they're pinned and not being updated automatically.
The teams that stayed safe had one thing in common: they treated dependency management as part of their security practice, not just routine package maintenance.
What Happened in Our Setup
I maintain a project called GloriaPPT — a typical Next.js app with 954 npm dependencies. When the axios advisory dropped, I wasn't refreshing Twitter. I got a Slack alert.
I built DevRadar Guard to answer one practical question fast: does this incident actually touch one of my repos? In this case, the flow looked like this:
- Signal Engine picked up the GitHub Advisory within its 30-minute collection cycle.
-
Exposure Engine matched it against GloriaPPT's
package-lock.json, whereaxioswas a direct dependency. - Guardrail Engine sent a Slack alert with the risk score, confidence level, and affected version.
No manual checking. No scrolling through threads or advisories. The alert landed with the information I needed to decide what to do next.
Axios Was One Incident. The Pattern Keeps Repeating.
Axios will be patched. Credentials will be rotated. Postmortems will be published.
But the pattern repeats. Before axios, it was event-stream. Before that, ua-parser-js. The attack surface keeps growing with every install that pulls in packages your team didn't explicitly choose or review.
The question isn't whether the next supply chain attack will happen. It's whether your repo will know about it before your CI/CD pipeline installs it.
What You Can Do Today
Even without new tooling, these steps can reduce your risk right away:
-
Pin your dependencies. Remove
^and~from critical packages. Use exact versions. -
Set
ignore-scripts=truein.npmrc. In this incident, that setting would have blocked the malicious install script. - Review your lockfile after every install. If a new transitive dependency appears that you didn't add, investigate.
-
Audit your CI/CD pipeline permissions. Does your build environment need network access during
npm install?
What We're Building
I'm also building DevRadar Guard around this workflow: early signal collection, repo exposure checks, and guardrail generation. Part of it is open source, including starter config for .npmrc, pre-install hooks, CLAUDE.md (security policy for AI coding agents), and GitHub Actions.
DevRadar Guard is still in Alpha and runs in alert-only mode. No automatic blocking, and no surprise PR failures. You stay in control.
If your team depends on npm and this workflow sounds useful, take a look at the starter kit or join the waitlist:
Top comments (0)