An attack that exploits name collisions between internal and public package registries.
Dependency confusion is a supply chain attack in which an adversary publishes a malicious package to a public registry (npm, PyPI, RubyGems) under the same name as a private, internal-only package used by a target organisation. When the target's package manager resolves dependencies, it may prefer the attacker's public copy — usually because it carries a higher version number — and silently execute attacker code during installation.
The technique was formalised in 2021 by security researcher Alex Birsan, who used it to obtain remote code execution inside Apple, Microsoft, PayPal, Uber, Shopify, Netflix, and more than thirty other major firms — and earned over $130,000 in bug bounties in a single research campaign.
The attack exploits three assumptions that package managers historically made:
package.json, an error stack trace, a screenshot in a blog post, or a stale GitHub commit.9999.9.9 — and embeds a postinstall script or import-time payload that phones home with environment variables, SSH keys, or CI secrets.npm install or pip install, the package manager consults both the internal mirror and the public registry. Without explicit priority rules, the highest semver wins — and the malicious package is pulled, installed, and executed.Dependency confusion is devastating because the attack surface is every internal package name a company has ever used, and the blast radius is arbitrary code execution on the developer or CI machine — which usually means cloud credentials, secrets, and source-repository tokens.
The mitigations are straightforward but require discipline: (1) scope locks — publish internal npm packages under an @my-org/ scope and claim that scope publicly; (2) private registry priority — configure package managers so the internal registry resolves first and public is a fallback, never an override; (3) explicit version pins and lockfiles that record the resolved URL, not just the version; (4) ingress filtering at the proxy layer to block resolution of names that match internal ones.
You cannot defend names you do not know about — platforms surface every package referenced across repos, CI, and production images.
Flag internal package names whose matching public namespace is still available — those are live bait for attackers.
If a package matching one of your internal names suddenly appears on npm or PyPI, you want to know within minutes, not weeks.
Policy gates can reject any build where a lockfile resolves an internal-name package to a public URL.
A platform can verify that every developer machine and CI runner is configured with the correct private-registry priority — and alert on drift.
Safeguard maintains a live inventory of every internal package name observed across your SBOMs, and cross-references that list against public-registry publications in near-real-time. If an unclaimed name appears publicly, the platform raises a high-severity supply chain finding and drafts the namespace-claim remediation.
Safeguard inventories every internal package you ship and checks the public namespaces on your behalf.