Security

Dependency Confusion Attacks: How They Work and How to Defend Your Supply Chain

·9 min read

The Attack in Brief

Dependency confusion, first described publicly by Alex Birsan in 2021, exploits a behaviour common to npm, pip, gem, and several other package managers: when a package name is requested, the manager may check both the private registry and the public registry, preferring the higher version number regardless of source. An attacker who discovers a private package name — via leaked package.json files, job postings, or public source code — can publish a malicious package with the same name to the public registry with a higher version number, causing developer and CI machines to pull the attacker's package instead of the internal one.

The Scale of the Exposure

Birsan's original research demonstrated successful package substitutions at Apple, Microsoft, PayPal, Shopify, Netflix, Yelp, and Tesla, among others. Subsequent research has found that the attack vector remains viable in many enterprise environments because package manager configuration is distributed across thousands of developer machines and CI configurations, and ensuring consistent scoping across all of them is operationally difficult.

Package Manager-Specific Vectors

  • npm/yarn: Private packages published without an npm scope (e.g., internal-utils instead of @company/internal-utils) are resolvable against the public registry. Scoped packages under an organisation's private scope are protected if the scope is registered on npmjs.com.
  • pip: --index-url replaces the default PyPI index, but --extra-index-url adds PyPI as a fallback. The latter is the vulnerable configuration.
  • Maven: Repository precedence in settings.xml and POM files determines resolution order. Placing the internal repository before Maven Central is necessary but not sufficient if snapshots are also resolved against Central.

Defence Controls

The primary defence is registry scoping: configuring package managers to resolve private package names exclusively from the private registry and never fall back to the public registry for those names. For npm this means using scoped package names under a registered organisation scope. For pip this means using --index-url (not --extra-index-url) for environments where all dependencies are available internally. For Maven this means configuring mirrorOf=* for the internal registry to ensure all resolution goes through it.

  • Audit all CI configuration files for --extra-index-url or equivalent fallback-enabling flags.
  • Register your internal package name prefixes and scopes on public registries to prevent squatting.
  • Enable package manager lockfiles and verify lockfile integrity in CI to detect unexpected resolution changes.
  • Implement supply chain security tooling that alerts on unexpected package sources in dependency graphs.

OSSeva's Supply Chain Monitoring

OSSeva's Assure service includes supply chain integrity monitoring that detects dependency resolution anomalies — packages resolving from unexpected sources, version bumps without corresponding internal publish events, and new transitive dependencies introduced between builds. These signals are the earliest warning of a dependency confusion or substitution attack in progress.

Conclusion

Dependency confusion is a structural vulnerability in the package resolution model, not a bug in any single tool. Defending against it requires architectural changes to how private packages are scoped and how registries are configured, not just one-time patching. The organisations most at risk are those with large numbers of unscoped private package names and inconsistent CI configuration management.

Tags

Supply ChainnpmPyPIDependency Confusion

Related articles

Ready to get your open source under control?

Talk to an OSSeva engineer about CVE coverage, compliance, and migration support for your stack.