InsightsSoftware & InfrastructureApril 1, 2026
Anatomy of a Supply Chain Attack

7 min read

Insight

Software & Infrastructure

Anatomy of a Supply Chain Attack

The axios compromise showed how a single hijacked account can deploy malware to millions of machines in minutes. The same structural vulnerability exists across npm, PyPI, and Docker.

Written By

Quandelia

In This Article
  1. 01.How It Worked
  2. 02.The Pattern Across Ecosystems
  3. 03.Why the Usual Defenses Fall Short
  4. 04.What Actually Reduces the Risk
  5. 05.The Bigger Picture

Open-source supply chain attacks exploit the same structural weakness everywhere: implicit trust in a small number of maintainer accounts, with no friction between publishing and execution. The defenses that work are structural, and most teams haven't adopted them.

On March 31, 2026, someone published two compromised versions of axios to npm. Axios has over 100 million weekly downloads. The malicious versions contained a hidden dependency that deployed a cross-platform remote access trojan to every machine that ran npm install during a two-hour window.

The attacker didn't touch a single line of axios source code. They hijacked the maintainer's npm account, added one dependency to package.json, and let the package manager do the rest. Google attributed the attack to UNC1069, a North Korean state-linked group active since 2018.

Two hours. One compromised account. Millions of potential targets. This is the economics of open-source supply chain attacks, and the pattern keeps repeating.

How It Worked

The mechanics are clean and worth understanding because they apply far beyond this one incident.

The attacker compromised the credentials of the primary axios maintainer, published versions 1.14.1 and 0.30.4, and added a new dependency: [email protected], created minutes earlier. When npm resolved the dependency tree, it pulled that package and ran its postinstall script automatically. That script was a two-layer obfuscated dropper. It detected the host OS, deployed a platform-specific RAT, harvested SSH keys, cloud tokens, and credentials from the local environment, then deleted itself and replaced its own package.json with a clean version to cover its tracks.

No code review would have caught it. The change was one line in a dependency manifest. The actual payload lived in a transitive package most developers would never inspect.

The Pattern Across Ecosystems

This is the same playbook that has been escalating for years, and it extends well beyond npm.

npm's track record speaks for itself. event-stream in 2018 (cryptocurrency theft via a hijacked package). ua-parser-js in 2021 (cryptominers and credential stealers). colors.js in 2022 (maintainer sabotage). In September 2025, attackers hijacked 18 packages including chalk and debug, with combined downloads exceeding 2.6 billion per week. Two months later, a self-replicating worm compromised 796 packages. Then axios.

PyPI faces the same structural risks. Python's package index has seen a surge of typosquatting attacks, where malicious packages are published with names similar to popular libraries (for example, python-binance vs python_binance). In 2024, researchers found over 400 malicious PyPI packages in a single campaign. PyPI's setup.py can execute arbitrary code during installation, the same lifecycle-script vector that makes npm attacks possible.

Docker images are another surface. Public registries host base images that millions of containers run on. A compromised base image propagates through every build that pulls it. Verified publishers and image signing (Docker Content Trust, Sigstore) exist, but adoption remains low for community images.

The common thread is always the same: a small number of maintainer accounts control packages that reach millions of systems, with minimal friction between publishing and execution.

Why the Usual Defenses Fall Short

Lockfiles help with the wrong scenario. They pin versions and prevent accidental upgrades, which matters. They do nothing for the developer who runs npm install or pip install on a fresh project and locks the compromised version from the start.

Code review misses it. The axios attack was one line in package.json. In a project with hundreds of dependencies, a new transitive package is invisible during review.

Vulnerability scanners are reactive. They check against known advisories. A zero-day supply chain attack is unknown until someone discovers and reports it, which is after the damage window has closed.

These aren't bad practices. They're insufficient against an attacker who can push code directly to the registry under a trusted name.

What Actually Reduces the Risk

The defenses that work are structural. They reduce the surface area rather than trying to detect malicious code after the fact.

Disable automatic script execution. In npm, set ignore-scripts=true in .npmrc and allowlist only the specific packages that genuinely need build steps. In Python, prefer wheels over source distributions, since wheels don't execute setup.py. This single change blocks the primary malware delivery mechanism.

Use deterministic installs in CI. npm ci in JavaScript, pip install --require-hashes or uv pip install with a lockfile in Python. These ensure your build installs exactly what was reviewed, with no resolution surprises.

Verify provenance where available. npm now supports provenance attestations that link a package to its source repo and build environment. PyPI has introduced trusted publishers via OIDC. Docker has content trust and Sigstore. When provenance is available, use it. When it isn't, treat that as a risk signal.

Add a version cooldown. Some registry proxies support a configurable delay between when a version is published and when it becomes installable. A 24-hour cooldown would have blocked the axios attack entirely. The malicious window lasted two hours.

Audit your dependency depth. A project with 30 direct dependencies can pull in 800 transitive ones. Each is code you've implicitly chosen to trust. Periodically review what you're actually installing, remove what you can, and favor lighter alternatives where they exist.

The Bigger Picture

Open-source supply chain attacks are escalating because the return on investment is extraordinary. One compromised account can reach millions of machines in minutes, across every operating system, through infrastructure that developers trust implicitly. State-sponsored actors have noticed. The axios attack was attributed to a North Korean group. This is no longer hobbyist territory.

The ecosystem is responding. npm deprecated classic tokens in late 2025 and pushed toward OIDC-based publishing. PyPI introduced trusted publishers. These are real improvements, but they only work when maintainers adopt them, and adoption is still low.

For engineering teams, the takeaway is straightforward. Every dependency is code you chose to run. Treat your install step with the same scrutiny you'd apply to a production deployment. The teams that internalize this build their pipelines accordingly: scripts disabled by default, deterministic installs, provenance checks, version cooldowns. The teams that don't are betting that the next attack won't land on a package in their tree. That bet keeps getting worse.