
Every modern application is assembled, not written from scratch. A typical install pulls in hundreds of open source packages, most of them transitive dependencies authored by people the developer will never meet. Each one runs with the same privileges as the code that pulled it in.
Attackers spent 2026 proving how far that single fact reaches. On March 31, a North Korean state actor hijacked the maintainer account behind Axios, one of the most widely used JavaScript HTTP clients at over 100 million weekly downloads, and published two poisoned releases that pulled in a phantom dependency and dropped a cross-platform remote access trojan the moment anyone ran npm install.
And just this month, the self-propagating Shai-Hulud worm tore through the keyv caching library and used stolen credentials to republish itself into more than 1,280 packages carrying billions of combined monthly downloads, hundreds of them within the first hour. Each time, one poisoned upload was enough to reach an entire ecosystem of downstream projects.
This month’s campaign maps the landscape end to end:
Let’s dig in.

Every language ecosystem is built on a package registry: npm for JavaScript, PyPI for Python, RubyGems for Ruby, crates.io for Rust, NuGet for .NET, and Go modules for Go. They differ in syntax but share one design. A project declares the packages it needs, and the registry’s tooling fetches those packages along with everything they depend on. A direct dependency is one your project names explicitly. A transitive dependency is one pulled in indirectly because something else requires it. Both run with the same privileges, and a single install commonly resolves to hundreds of transitive packages.
The core abuse primitive is automatic code execution during installation. In npm, a package’s lifecycle scripts (preinstall, postinstall, prepare) run automatically at set points during an install, and Python packages run their own setup code during pip install the same way. Even where install scripts are disabled, code at the top level of a module runs the moment it is imported, giving attackers an import-time vector that bypasses install-only defenses.
Installing a package is not downloading inert data. It is running the author’s code. Enterprises widen the gap further by pulling public packages while also maintaining private internal ones, the dual-source model where dependency confusion lives.
Package poisoning techniques differ only in how an attacker gets malicious code into a package a developer already trusts. The execution and impact are the same, and each technique recurs across every ecosystem.
Register a package whose name resembles a popular one and rely on a developer’s typo or fuzzy memory. North Korea’s Lazarus Group used this on npm with lookalike validators that carried BeaverTail, an infostealer that harvests browser-stored credentials and cryptocurrency wallets, and the same technique drives recurring malware campaigns on PyPI.
Publish a public package with the same name as an organization’s private internal package but a higher version number, so the resolver prefers the attacker’s copy. Security researcher Alex Birsan proved it cross-ecosystem in authorized bug bounty research, gaining code execution inside Apple, Microsoft, Tesla, and others; the clearest malicious example is torchtriton on PyPI, where a public package shadowed a PyTorch internal dependency name.
Steal a legitimate maintainer’s publishing credentials, then ship a malicious version of a trusted package. Because the name and history are genuine, this is among the hardest to spot. It is how the Axios compromise began, and on PyPI the LiteLLM gateway was poisoned after its publish token was stolen from a compromised CI action.
Inject malicious code into a package the attacker now controls, often automated by a worm that republishes across every package a compromised maintainer owns. This is how the Shai-Hulud worm and the TeamPCP group’s campaigns spread, and where a worm hijacks a release pipeline, it maps to compromise of the software supply chain itself.
Dive into this month’s campaign to build a working model of how software supply chain attacks operate and how to defend against them.