Safeguard
Open Source Security

How Snyk identifies dependency confusion attacks in priva...

A technical look at how Snyk detects dependency confusion attacks — from vulnerability database malicious-package flags to registry scoping and Advisor scoring.

Vikram Iyer
Security Researcher
7 min read

In February 2021, security researcher Alex Birsan published a technique that let him execute code inside the networks of Apple, Microsoft, PayPal, Shopify, Netflix, Uber, and dozens of other companies — without touching their infrastructure directly. He simply published packages to the public npm and PyPI registries using the same names as internal packages he'd found referenced in leaked package.json files, requirements.txt files, and JavaScript source maps. Build systems configured to check public registries pulled his packages instead of the private ones, because his versions were numbered higher. The technique, now called dependency confusion, earned him over $130,000 in bug bounties and forced package managers, registries, and scanning vendors to rethink how they resolve dependency names. Snyk, one of the more widely deployed software composition analysis (SCA) tools, has built specific detection logic around this exact failure mode. Here's how that detection mechanically works.

What makes dependency confusion different from a typical vulnerable dependency?

A typical SCA finding flags a package that is already installed and contains a known CVE. Dependency confusion is different because the dangerous package isn't supposed to be installed at all — the attack works by getting the wrong package resolved in the first place. If a company has an internal package called acme-auth-utils published only to a private registry (Artifactory, Nexus, GitHub Packages, or a private npm scope), an attacker can publish a public package with the identical name and a higher version number — say 9.9.9 versus the internal 1.2.0. Most package manager resolution logic, absent explicit registry pinning, treats "highest version wins" as the tiebreaker across registries it's configured to check, and defaults toward the public registry. This means the vulnerability isn't in a line of code — it's in registry configuration and namespace management, which is why detecting it requires comparing what's declared against where it actually resolves from, not just scanning for known CVE identifiers.

How does Snyk flag packages that could be exploited for namespace confusion?

Snyk's detection centers on cross-referencing internal package manifests against public registry namespaces to identify name collisions before an attacker can exploit them. When Snyk Open Source scans a project's manifest and lock files (package.json/package-lock.json, requirements.txt, pom.xml, and equivalents), it evaluates the resolved source of each dependency, not just its declared name. Snyk's documentation and research team have specifically called out that organizations using internal package names without a reserved namespace (an npm scope like @yourcompany/package-name, or an equivalent grouping in other ecosystems) are exposed, because an unscoped name is a name anyone can register publicly. Snyk's guidance since its 2021 dependency confusion research has pushed customers toward auditing their internal package names against what already exists — or could be squatted — on the corresponding public registry, which is the direct analog of the reconnaissance step Birsan used to find his targets.

How does Snyk's vulnerability intelligence catch malicious packages after they're published?

Snyk maintains a Vulnerability Database that includes a distinct "malicious package" category, populated by its security research team and automated pipelines that continuously monitor npm, PyPI, RubyGems, and Maven for newly published packages exhibiting suspicious behavior. This includes packages with names that closely mirror known private or popular package naming conventions, packages published with unusually high version numbers relative to their publish history, and packages containing install-time scripts that exfiltrate environment variables or make outbound network calls — all hallmarks of a dependency confusion payload. When Snyk's researchers confirm a package is malicious, it's added to the Snyk Intel Vulnerability Database with a Malicious Package classification, and any customer whose snyk test or snyk monitor scan resolves that package — even transitively — gets flagged immediately, independent of whether a CVE has been assigned. This closes the gap for attacks that are, by nature, too fast-moving and targeted to wait for CVE publication.

Why does registry configuration matter as much as scanning?

Detection after the fact matters less than resolution never happening in the first place, which is why Snyk's published guidance treats registry configuration as the primary control and scanning as the backstop. Snyk's recommendations, consistent with npm's and Microsoft's own post-Birsan guidance, include explicitly mapping internal scopes to private registries in .npmrc (@yourcompany:registry=https://your-private-registry), setting pip.conf or pip.ini to pin index URLs rather than relying on --extra-index-url (which checks multiple indexes and is a known confusion vector), and reserving placeholder packages on public registries for any internal name that must remain unscoped. Snyk Open Source scans can flag manifests that lack this pinning, which is a configuration-level finding distinct from a vulnerable-package finding — it's closer to a misconfiguration check than a traditional SCA alert, but it targets the actual root cause rather than a symptom.

Does Snyk's package scoring help distinguish a legitimate publish from an attack?

Snyk Advisor, the package health scoring feature built into Snyk Open Source, contributes secondary signal by scoring packages on popularity, maintenance cadence, community size, and security history — factors that a freshly published dependency-confusion payload will almost always fail. A package published days ago with zero prior version history, no GitHub repository linkage, and a single maintainer account is a poor Advisor score by construction, which is a useful heuristic layer on top of the malicious-package classification, though it's a scoring signal rather than a definitive detection mechanism on its own. Snyk documentation is explicit that Advisor scores are meant to inform manual review and policy decisions, not to auto-block installs by themselves — teams typically pair Advisor scores with CI gating rules that block installs below a policy threshold.

What should teams do beyond running a scanner?

Scanning catches what's already resolved; preventing dependency confusion requires namespace hygiene that no scanner can retroactively fix once a malicious package has been pulled into a build. The baseline steps documented across Snyk's research, npm's official guidance, and Microsoft's original 2021 mitigation advisory are consistent: scope every internal package under a reserved namespace, pin registries explicitly per scope rather than relying on resolution order, avoid publishing internal package names or structures in public-facing build logs and source maps, and periodically audit which internal names have public-registry equivalents that don't belong to you. These are organizational and configuration changes, not something a single SCA scan enables — which is why dependency confusion is often framed as a supply chain governance problem that scanning tools support rather than fully solve.

How Safeguard Helps

Dependency confusion is fundamentally a provenance problem — it exploits the fact that a build process often can't tell the difference between "the package we meant to install" and "a package with the same name from somewhere else." Safeguard approaches this by continuously verifying the provenance and integrity of dependencies as they move through your CI/CD pipeline, not just at scan time. That means validating that packages resolve from the registry and namespace you actually intend, flagging registry configuration drift before a build silently starts pulling from an unintended public source, and correlating newly observed package versions against your organization's actual internal package inventory. Combined with policy enforcement at the pipeline level — blocking builds that resolve dependencies outside of approved registries or namespaces — Safeguard is built to catch the moment a build would have resolved the wrong package, rather than relying solely on detecting the malicious package after publication. For teams building out software supply chain security programs, pairing registry-level provenance enforcement with SCA scanning closes both sides of the dependency confusion attack surface: the resolution-time gap and the post-publication detection gap.

Never miss an update

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