TL;DR

On 2026-03-31, two malicious versions of axios (70M+ weekly downloads) were published. They connected to a C2 owned by the Sapphire Sleet threat actor to pull a remote access trojan. Because Axios is commonly auto-updated, projects with permissive version ranges fetched the malware on the next install or CI run. Now tracked as CVE-2026-34841 (CVSS 9.8) via the downstream advisory on @usebruno/cli, which transitively pulled the bad axios.

What happened

The two malicious Axios versions were 1.14.1 and 0.30.4. They injected a hidden dependency, plain-crypto-js@4.2.1 — a package never imported anywhere in the axios source. Its only job was a postinstall script acting as a cross-platform RAT dropper (macOS, Windows, Linux), contacting sapphire-sleet-attributed infrastructure on install and pulling a second-stage RAT for persistent access to dev machines and CI runners.

Detected within hours and removed, but the auto-update vector means thousands of ^x.y.z and ~x.y.z ranges resolved to the malicious versions during the window.

Downstream blast radius — @usebruno/cli (CVE-2026-34841): Bruno (the API client/IDE) shipped a CLI that pulled the compromised axios transitively. Anyone who ran npm install of @usebruno/cli between ~00:21 and ~03:30 UTC on 2026-03-31 may have resolved the malicious axios and executed the RAT dropper. Bruno pinned axios to a safe version; @usebruno/cli < 3.2.1 is affected — upgrade to ≥ 3.2.1. This is a textbook reminder that the worry isn't only the famous package — it's everything that depends on it.

Am I affected?

# Show all axios versions in your tree
npm ls axios --all

# Check lockfile for the bad versions (1.14.1 / 0.30.4) and the tell-tale dropper dep
grep -A2 '"axios"' package-lock.json
grep -nE '"(axios)":\s*"(1\.14\.1|0\.30\.4)"|plain-crypto-js' package-lock.json

# Bruno CLI users: confirm you're on a fixed release
npm ls @usebruno/cli 2>/dev/null

If your package.json uses "axios": "^1.x.x" and you installed between 2026-03-31 and the takedown, your lockfile will have pinned the malicious version's hash. The clearest single IOC is the presence of plain-crypto-js@4.2.1 anywhere in your tree — it has no legitimate use.

# Check for outbound connections to known Sapphire Sleet C2 (consult Microsoft Security Blog for current IOCs)
# Generic: look at dev-machine network logs for unexpected outbound from node processes around the install date

If you are affected

playbooks/if-you-installed-a-bad-npm-package.mdplaybooks/rotating-cloud-credentials.md

Prevention

prevention/npm-hardening.md — pin exact versions, use npm ci not npm install in CI

Sources