DEV Community

HorseyofCoursey
HorseyofCoursey

Posted on

How the Axios Supply Chain Attack Worked - And How to Detect It Earlier

What happened

On March 31, 2026, attackers compromised the npm account of the lead Axios maintainer and published two malicious versions of one of the most downloaded JavaScript libraries in existence with 100 million weekly downloads.

The attack was surgical. They didn't touch a single line of Axios source code. They added one hidden dependency to package.json: plain-crypto-js@4.2.1.

That dependency ran a postinstall script that deployed a cross-platform Remote Access Trojan (RAT). Within 89 seconds of publish, real developer machines were already infected via auto-updating CI/CD pipelines.

The malicious versions were removed in about 3 hours. But the window was enough to cause damage.

Why existing tooling missed it

Static scanners like Dependabot and npm audit check against known CVE databases. There was no CVE to check for this attack because it was brand new. By the time a CVE existed, the damage was done.

Provenance attestation would have caught it. The malicious versions were published directly via CLI, bypassing the normal GitHub Actions workflow and leaving no SLSA attestation. But adoption isn't universal yet.

What would have caught it faster

The attack had two very detectable signals:

Signal 1 — package.json changed
plain-crypto-js appeared as a new dependency in a mature, stable library that hadn't added a dependency in months. A simple diff against a known-good baseline would have surfaced this the moment the malicious version published.

Signal 2 — network call within 2 seconds of install
The malware called sfrclak.com almost immediately. Any system watching DNS lookups during package installation would have caught this with hard evidence. Not a guess, an actual domain.

Building a four layer detector

After the attack I built pakrat, an open source behavioral monitor that watches 187 npm packages every 5 minutes using four detection layers.

Layer 1 — Manifest diffing

Every scan fetches the latest package metadata from the npm registry and diffs it against a stored baseline. New dependencies, new install scripts, version changes - all flagged immediately.

The Axios attack would have triggered this the moment plain-crypto-jsappeared in package.json.

Layer 2 — Docker sandbox with tcpdump

Any package that triggers a manifest alert gets installed in an isolated Docker container while tcpdump monitors all DNS lookups. Known good domains like registry.npmjs.org are filtered out. Anything else surfaces as a flag.

sfrclak.com would have appeared here within seconds.

Layer 3 — Pattern matching

Install output gets scanned for credential harvesting patterns: .ssh directory access, .aws config reads, environment variable access, base64 encoding. Secondary signal, but useful context alongside harder evidence.

Layer 4 — eBPF kernel monitoring

This is the interesting one and my favorite.

bpftrace probes attach at the host kernel level while the container runs. Every execve, openat, and connect syscall is captured: process execution, file access, network connections, all from outside the container's execution environment.

The package has no visibility into this layer. It can't fingerprint it, can't detect it, can't evade it. Even sophisticated malware that checks for Docker artifacts and goes dormant would still reveal itself by the act of checking, because those checks are syscalls too.

What the output looks like

Running pakrat against a simulated Axios-style attack:

pakrat detects threat in terminal

Discord alert hits your phone instantly.

Discord alert

Public scan log

Every scan updates scan-log.json in the GitHub repo, a public, auditable history of what 187 packages looked like at every point in time. Anyone can query it without running anything themselves.

What's next

The VM-based sandbox is the next layer — QEMU/KVM running a convincing developer machine with realistic dotfiles, browsing history, VS Code installed. A RAT that detects Docker and goes dormant won't detect a real VM. eBPF probes at the hypervisor level watch everything regardless.

PyPI support is also on the roadmap. The litellm attack last week showed the Python ecosystem is just as exposed.

Try it

GitHub: https://github.com/HorseyofCoursey/pakrat

Self-hosted setup is straightforward: Ubuntu VPS, Docker, Node.js 22, and a Discord webhook. The README walks through everything.

Contributions welcome, especially package whitelist additions and suggestions for the watched package list.

Top comments (0)