Togoder security

Glossary

What is dependency confusion?

Also called: substitution attack, namespace confusionUpdated

Definition

Dependency confusion (also called a substitution attack) is publishing a package to a public registry under the same name as a company's internal package, so that a misconfigured package manager installs the public, attacker-controlled version instead.

How dependency confusion works

Many companies publish internal packages, such as acme-billing-client, to a private registry. If the build is configured to look at both the private and the public registry, the package manager has to choose between two packages with the same name. Several tools pick the highest version number, wherever it comes from.

An attacker who learns the internal name (from a leaked package.json, a JavaScript source map or an error message) publishes acme-billing-client@99.0.0 to the public registry. The next build installs it, and its install script runs inside the company's CI.

Security researcher Alex Birsan demonstrated this in 2021 against dozens of large companies, including Apple, Microsoft and PayPal, earning over $130,000 in bug bounties.

How to prevent dependency confusion

  • npm: publish internal packages under a scope you own (@acme/billing-client) and map that scope to your registry in .npmrc: @acme:registry=https://npm.acme.internal/. Also claim the scope on the public registry.
  • pip: avoid --extra-index-url, which merges indexes. Use a single --index-url pointing at a proxy that serves your private packages and mirrors PyPI.
  • Commit lockfiles and install with npm ci or hash checking, so a new higher version cannot appear without a reviewed lockfile change.
  • Register placeholder packages for your internal names on public registries.

Frequently asked questions

Are scoped npm packages safe from dependency confusion?

Yes, if the scope is mapped to your private registry in .npmrc and you own the same scope on npmjs.com. Unscoped internal names are the main risk.

Does a lockfile prevent dependency confusion?

Mostly. Installing strictly from a committed lockfile pins the exact source and integrity hash, so a public look-alike cannot be substituted until someone regenerates the lockfile.