All posts
SecuritySupply ChainEducation

Supply Chain Attacks Explained: When the Package Is the Threat

You review your code. You audit your PRs. But what about the 70+ packages your project pulls in automatically? Supply chain attacks target the software you build with, not the software you write.

StackRadar Team6 min read

Most security thinking focuses on the code you write. SQL injection, authentication flaws, insecure APIs — vulnerabilities in your application's own logic. But some of the most damaging attacks of the past decade targeted something most teams barely think about: the code they depend on.

TL;DR

  • A supply chain attack targets the libraries and tools you build with — not the code you write yourself
  • The average JavaScript project has over 1,000 packages in node_modules, written by hundreds of people you've never vetted
  • Attack methods include: maintainer takeover, stolen credentials, typosquatting, dependency confusion, and long-game social engineering
  • Real incidents — event-stream, XZ Utils, node-ipc — show this is an active threat, not a theoretical one
  • Defence starts with knowing exactly what is in your dependency tree and monitoring it for unexpected changes

What is a supply chain attack?

When you run npm install or pip install, you are not just downloading code written by one team. You are pulling in everything that code depends on, and everything those dependencies depend on, recursively. The average JavaScript project has over 1,000 modules in node_modules, written by hundreds of different people.

A supply chain attack exploits this trust chain. Instead of attacking your application directly, an attacker compromises something your application depends on. When your project installs or imports the compromised package, the malicious code runs in your environment — with your permissions, with access to your secrets.

How these attacks happen

Maintainer takeover

An attacker contacts an inactive maintainer and offers to "help" with an abandoned package. Once they have publish access, they inject malicious code. This is what happened with event-stream in 2018 — two million weekly downloads, handed to a stranger, used to target a bitcoin wallet.

Stolen or compromised credentials

A legitimate maintainer's npm or PyPI account is compromised through phishing, a reused password, or a data breach. The attacker publishes a malicious version under the real maintainer's account. Because the name and author are trusted, package managers install it automatically.

Typosquatting

An attacker publishes a package with a name nearly identical to a popular one — lodahs instead of lodash, or crossenv instead of cross-env. A single typo in a package.json pulls in the wrong code entirely.

Dependency confusion

Companies often use internal packages with names that do not exist on public registries. An attacker publishes a public package with the same name at a higher version. Package managers that check public registries first install the attacker's version instead of the internal one. Security researcher Alex Birsan demonstrated this at scale in 2021, getting code into Apple, Microsoft, and PayPal systems.

Long-game social engineering

The most patient version: spend months or years making genuine contributions to a project, build real trust, gain commit access, then insert a payload. This is exactly what happened with XZ Utils in 2024 — a two-year campaign that came within days of compromising SSH on millions of Linux servers.

Protestware

Sometimes the threat is the legitimate maintainer themselves. The author of node-ipc shipped code that deleted files on Russian and Belarusian computers in 2022. The author of colors.js deliberately broke his widely-used library to protest large companies not contributing back to open source.

Why it is hard to defend against

The uncomfortable reality: every time you run a dependency install, you are implicitly trusting the security practices, motivations, and account security of hundreds of developers you have never met.

You cannot read every line of every package you depend on. There are too many, they change too frequently, and traditional security reviews do not cover this surface. The threat is real, active, and growing — package registries have seen supply chain attacks increase sharply year over year.

What actually helps

  • Lock dependency versions with lock files so you always know exactly what you are installing
  • Keep a complete inventory of all direct and transitive dependencies across your codebase
  • Run automated vulnerability checks in CI as a release gate, not an afterthought
  • Monitor for unexpected changes — a new transitive dependency appearing in a minor update is worth investigating
  • Use package registries that support signed provenance (npm provenance, PyPI attestations)
  • Apply least privilege — packages should not have access to secrets or filesystem paths they do not need

None of these eliminate supply chain risk entirely. But they shrink the window between a malicious package being published and your team knowing about it — and the speed of detection is often what determines the severity of the outcome.


StackRadar is built around this problem: continuous, accurate visibility into everything in your dependency tree — so when something unexpected changes, you know immediately.

More from the StackRadar blog

All posts