Safeguard
Cloud Security

Dependency Confusion Attack

How dependency confusion attacks exploit registry name collisions to run attacker code inside corporate networks, from Alex Birsan's 2021 research to the 2022 PyTorch breach.

Aman Khan
AppSec Engineer
6 min read

In February 2021, security researcher Alex Birsan disclosed a technique that let him execute code inside the internal networks of Apple, Microsoft, PayPal, Shopify, Netflix, Tesla, and more than 30 other companies — without touching their production systems directly. He called it dependency confusion, and it exploited a simple, overlooked default: when a build tool resolves a package name that exists both on a public registry like npm or PyPI and on a private internal registry, it often installs whichever one has the higher version number, regardless of source. Birsan collected over $130,000 in bug bounties for the research. Five years later, the attack pattern is still live: threat actors scrape internal package names out of leaked config files, job postings, and open-source manifests, publish malicious lookalikes to public registries, and wait for a CI pipeline to pull them in. This post breaks down how the attack actually works, what's happened since 2021, how a competitor like Aqua Security approaches detection, and where Safeguard fits.

What Is a Dependency Confusion Attack?

A dependency confusion attack tricks a package manager into installing an attacker-controlled public package instead of an organization's internal, same-named private package. Most build ecosystems — npm, pip, RubyGems, and until recently even some internal Maven/NuGet feeds — were designed around a simple assumption: a single global namespace where the "best" version wins. If a company has an internal package called acme-auth-utils sitting at version 1.4.0 on a private artifact server, an attacker only needs to publish a package with the exact same name — say, version 9.9.9 — to the public npm registry. When a developer's laptop or a CI runner resolves dependencies without an explicit, locked-down registry scope, many resolvers see the public 9.9.9 as "newer" and fetch it instead, silently substituting attacker code — including arbitrary postinstall scripts — for the trusted internal library. No phishing, no exploit chain, no credential theft required. Just a name collision and a version number.

How Did Alex Birsan's 2021 Research Expose the Flaw?

Birsan proved the attack was systemic rather than theoretical by publishing counterfeit packages that phoned home from inside the networks of more than 35 companies, including Microsoft, Apple, PayPal, Shopify, Netflix, Yelp, Uber, and Tesla. He found internal package names by combing through leaked package.json files on GitHub, internal error messages, and JavaScript source maps that inadvertently referenced private module names. Microsoft awarded the single largest bounty, $40,000, and subsequently published its own mitigation guidance for the npm ecosystem. Total payouts across all affected companies topped $130,000. In the months that followed, npm introduced scoped packages as a stronger namespace boundary, PyPI added reserved-namespace protections, and several enterprise artifact-manager vendors shipped "upstream priority" controls so private registries could be forced to win resolution conflicts by default rather than by accident.

Why Do Internal Package Names Leak in the First Place?

Internal package names leak because they routinely appear in artifacts nobody thinks to sanitize before they become public. Open-sourced internal tooling that still imports a private helper library, minified JavaScript source maps that expose require() paths, .npmrc or pip.conf files accidentally committed to public repos, job postings that describe an internal "platform-core" or "auth-service" package by name, and CI logs uploaded to public status pages all hand attackers exactly what they need: a valid, guessable internal package name to squat on. In the weeks immediately following Birsan's disclosure, JFrog's security research team found copycat packages already live on npm attempting the same trick against Amazon, Lyft, Slack, and Zillow — evidence that the technique was trivially reproducible once the method was public, and that reconnaissance, not exploitation, is usually the hard part attackers need solved for them.

What Real-World Incidents Have Followed Since 2021?

Dependency confusion moved from proof-of-concept to a confirmed production compromise on December 30, 2022, when the PyTorch team disclosed that its PyTorch-nightly package on PyPI had been compromised via a malicious torchtriton dependency. The attacker published a package on the public PyPI index with the same name as an internal dependency PyTorch's nightly builds pulled from a private index, and because the public copy carried a higher version number, pip installed the malicious one on machines that ran pip install torch-nightly between December 25 and 30, 2022, exfiltrating system data and SSH keys. PyTorch's maintainers had to remove the compromised package, rename the internal dependency, and publicly advise anyone who had installed nightly builds in that window to treat their machine as compromised. It remains one of the clearest documented cases of dependency confusion causing real exfiltration rather than a bug-bounty proof-of-concept, and it demonstrates that even security-conscious, high-profile open-source projects can miss a private-to-public naming collision.

How Does Aqua Security Approach Dependency Confusion Detection?

Aqua Security addresses dependency confusion mainly through its open-source Trivy scanner and the software supply chain module inside the Aqua Platform, which scan SBOMs, container images, and repositories for known-malicious or suspicious packages after they have already been pulled into a build or image. That model is effective for catching packages that match published threat-intelligence signatures, but it is inherently after-the-fact: the scan runs once an artifact exists, not at the moment a resolver decides which registry to trust. Aqua's broader strength is its CNAPP footprint — container runtime protection, cloud workload posture, and Kubernetes security — so dependency confusion detection shows up as one signal inside a much larger cloud-native platform rather than as a dedicated, registry-level policy engine purpose-built to stop name-collision resolution before install time. For teams whose primary exposure is the build and packaging pipeline rather than runtime container workloads, that can leave a gap between "we scanned the image" and "we stopped the resolver from ever fetching the wrong package."

How Safeguard Helps

Safeguard is built around closing exactly the gap that makes dependency confusion possible in the first place: uncontrolled, ambiguous package resolution. Rather than waiting for a malicious package to land in an image and then flagging it, Safeguard enforces registry-source policy at resolution time, so a build that should only ever pull acme-auth-utils from your internal registry cannot silently fall back to a same-named public package, no matter what version number an attacker publishes. Safeguard also continuously monitors public registries — npm, PyPI, RubyGems, crates.io, and Maven Central — for newly published packages that match the naming patterns of your internal libraries, so you get an alert the moment a squatter registers a lookalike, not after it's already been fetched by a CI job. On top of that, Safeguard maintains a live SBOM and dependency graph for every service, correlating internal package names against public registry activity so security teams can see exposure before an incident, not during a postmortem. For organizations that have open-sourced internal tools, posted engineering job listings that reference internal service names, or simply grown too large to track every private package name by hand, Safeguard closes the loop between "we know this happens" and "we can prove it can't happen to us" — turning a five-year-old, still-active attack technique into a solved problem rather than a recurring audit finding.

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.