In February 2021, security researcher Alex Birsan quietly slipped code into the internal build systems of Apple, Microsoft, PayPal, Tesla, Netflix, Uber, Shopify, and more than 30 other companies — without touching a single corporate network. His method: publishing public packages that shared names with the companies' private, internal-only dependencies, then waiting for misconfigured package managers to pull the public (and higher-versioned) copy instead. He collected over $130,000 in bug bounties and gave the technique a name that has since become one of the most searched terms in application security: the dependency confusion attack. Five years later, the technique is still working, still spreading across npm, PyPI, RubyGems, and NuGet, and still catching security teams off guard. Chainguard and others have pushed the industry toward hardened base images and minimal containers — but that doesn't address the package resolution problem at the root of dependency confusion. Here's what the attack actually is, how it evolved, and what closes the gap.
What Is a Dependency Confusion Attack?
A dependency confusion attack tricks a build system into downloading a malicious public package instead of a company's intended private, internal one. Most package managers — npm, pip, and their peers — default to checking multiple registries (public and private) when resolving a dependency, and many will simply install whichever version number is highest, regardless of source. If an attacker learns the name of an internal package (often leaked in a public package.json, a job posting, an open-sourced snippet, or a leaked build log) and publishes a same-named package to the public registry with a higher version number — say, 9.9.9 instead of an internal 1.0.4 — the build system pulls the attacker's code and executes it inside the company's CI/CD pipeline, often with elevated credentials attached. No phishing, no credential theft, no network breach required. Birsan's original disclosure affected companies including Apple, Microsoft, and Netflix, proving the technique worked at the scale of the world's largest engineering organizations.
How Did Attackers Weaponize the Technique After 2021?
Attackers weaponized dependency confusion within weeks of Birsan's public write-up, and by mid-2021 security firms including Sonatype and JFrog were tracking hundreds of copycat packages exploiting the same namespace-collision logic. Unlike Birsan's ethical research, which used benign beacon payloads to prove exploitation, real-world actors used the same technique to drop cryptominers, reverse shells, and credential stealers. In 2022, researchers found dependency confusion packages targeting German companies including Zalando, Grammarly, and Bayer, using internal package names scraped from leaked source code on public repositories. By 2023, Sonatype's State of the Software Supply Chain report counted 245,032 malicious open source packages identified that year alone — more than the combined total of every prior year tracked — with dependency confusion and typosquatting cited as two of the fastest-growing delivery mechanisms behind that spike.
What Other Malicious Dependency Techniques Compound the Risk?
Dependency confusion sits alongside a growing family of malicious dependency techniques, including typosquatting, protestware, and maintainer account takeovers, each of which has produced real production incidents. In November 2021, the popular ua-parser-js npm package — with roughly 8 million weekly downloads — was compromised after its maintainer's npm account was hijacked, pushing versions that installed cryptominers and password stealers directly into downstream applications. In January 2022, the maintainer of colors and faker.js, two npm packages downloaded a combined tens of millions of times weekly, intentionally sabotaged his own libraries, printing garbled text and infinite loops in a protest over unpaid open source labor — a reminder that "malicious" doesn't always mean external. And in 2022, the PyPI packages ctx and phpass were hijacked by an attacker who took over an expired maintainer email and pushed versions exfiltrating environment variables, including AWS keys, from every machine that installed them. Each of these techniques exploits the same underlying trust assumption: that a package name and version number are a reliable proxy for safe, reviewed code.
Why Doesn't a Hardened Base Image Stop Dependency Confusion?
A hardened base image doesn't stop dependency confusion because the attack happens during dependency resolution and build, not inside the runtime container. Chainguard's core product line — minimal, distroless container images built to reduce CVE counts at the OS and base-layer level — is genuinely useful for shrinking a container's attack surface once an application is packaged. But dependency confusion, typosquatting, and account-takeover attacks all occur earlier in the pipeline, at the moment npm install, pip install, or a CI job resolves and fetches source packages from public and private registries. A minimal, hardened base image built on top of a compromised ua-parser-js or a confused internal package still ships the malicious code — it's just running in a smaller, cleaner container. Reducing base-image CVEs and preventing malicious package ingestion are complementary problems, not the same one, and organizations that only invest in the former still leave their build pipelines exposed to the latter.
How Common Are These Attacks Today?
These attacks are now a routine, daily occurrence rather than a rare event: automated scanners upload thousands of malicious or confusable packages to public registries every month, and npm alone has had to pull down batches of over 1,200 malicious packages in a single sweep, as documented by Socket and Phylum in multiple 2023 and 2024 disclosures. Phylum's research team has repeatedly identified dependency confusion campaigns targeting specific companies by name — including a 2023 campaign that mimicked internal package names belonging to a major German telecom and automotive suppliers within days of those names appearing in public job listings and GitHub repos. The economics favor the attacker: publishing a package costs nothing, automated tooling can scan for leaked internal package names at scale, and a single successful confusion event can grant code execution inside a CI/CD environment with build secrets, cloud credentials, and signing keys attached.
How Can Organizations Prevent Dependency Confusion Attacks?
Organizations prevent dependency confusion primarily by controlling where their package managers are allowed to resolve dependencies from, not by hoping attackers never learn internal package names. The baseline fixes are well established: reserve or "claim" internal package names on public registries even if you never publish real code to them, configure scoped packages (@yourcompany/package-name) so npm cannot silently fall back to the public registry, pin exact versions and lockfiles instead of allowing floating version ranges, and configure private registries (Artifactory, Nexus, Verdaccio) with explicit allow-lists rather than pass-through resolution to the public internet. Beyond configuration, teams need continuous visibility: monitoring for newly published packages that match internal naming conventions, alerting on unexpected version bumps in the dependency graph, and verifying package provenance and maintainer history before a new dependency is pulled into a build. None of this is exotic — it's operational discipline that most organizations simply haven't automated yet.
How Safeguard Helps
Safeguard is built to close exactly this gap between "we have a hardened container" and "we know what's actually flowing into our build pipeline." Where hardened-image vendors like Chainguard reduce risk at the base-layer and OS-package level, Safeguard focuses on the dependency supply chain itself — the npm, PyPI, and internal packages your CI/CD systems resolve on every build.
Safeguard continuously monitors your dependency graph for known dependency confusion indicators: internal package names that also exist publicly, unexpected version jumps that don't match your internal release cadence, and newly published packages that structurally resemble typosquats of your existing dependencies. When a package's provenance, maintainer history, or publish pattern deviates from an established baseline, Safeguard flags it before it reaches a build, rather than after a compromised version has already executed with your CI credentials attached.
Because dependency confusion and account-takeover attacks both hinge on trust in a name and a version number, Safeguard verifies package identity and origin against a continuously updated threat intelligence feed drawn from real-world incidents — including the registry-hijack and confusion campaigns referenced above — so your team isn't relying on manual registry configuration alone to catch the next one. Combined with policy enforcement for scoped packages, lockfile integrity checks, and alerting on anomalous publish activity tied to your organization's naming conventions, Safeguard gives security and platform teams the visibility that hardened images were never designed to provide: confidence that the code entering your pipeline is the code you actually meant to install.