Package registries have quietly become one of the most contested attack surfaces in enterprise software, and NuGet — the default package manager for the .NET ecosystem, serving an estimated 6+ million developers and hosting more than 460,000 unique packages on nuget.org — is no exception. Since Alex Birsan's original "dependency confusion" disclosure in February 2021 demonstrated that public package registries could be tricked into serving attacker-controlled code ahead of internal packages at companies including Apple, PayPal, and Netflix, the technique has proliferated across every major ecosystem. NuGet's architecture — which by default resolves package names against nuget.org unless explicitly scoped — has made it a persistent, if underexamined, target. Security researchers have flagged a steady cadence of NuGet-specific incidents in the years since, from typosquatted packages mimicking popular libraries to a disclosed 2023 campaign that hid malware inside a package impersonating industrial automation tooling. This report examines what dependency confusion looks like on NuGet specifically, why the ecosystem remains structurally exposed, and what security and platform teams should be doing about it now.
What Dependency Confusion Looks Like on NuGet
Dependency confusion exploits a simple resolution ambiguity: when a build system is configured to pull packages from both a private/internal feed and the public nuget.org feed, and no explicit source mapping is enforced, the package manager may resolve a dependency name to whichever source offers the higher version number — regardless of which source the developer intended. An attacker who learns (or guesses) the name of an internal package can publish a same-named package to nuget.org with an artificially high version number, and dependent builds will silently pull the malicious public package instead of the trusted internal one.
This is distinct from typosquatting, where attackers register near-identical names (Newtonsoft.Json vs. NewtonsoftJson) hoping for a fat-fingered install. Dependency confusion instead relies on organizations leaking internal package names — through public GitHub repos, job postings, conference talks, error messages, or even internal documentation indexed by search engines — and then exploiting the default trust NuGet places in its public feed as a fallback resolution source.
NuGet's ecosystem-specific risk factors compound the problem. Unlike npm's scoped packages (@org/package), which provide some namespace isolation, NuGet package IDs are flat and globally unique on nuget.org, meaning any internal package name that hasn't already been claimed publicly is immediately squattable. Combined with the .NET ecosystem's heavy use of internal, enterprise-only libraries for things like proprietary SDKs, internal tooling wrappers, and legacy line-of-business components, NuGet presents a particularly attractive target for confusion-style attacks against large enterprises — the same organizations most likely to run private feeds like Azure Artifacts, MyGet, or on-prem NuGet servers alongside the public registry.
A Timeline of Escalating Incidents
The risk is not theoretical. Several disclosed incidents illustrate how the threat has evolved from proof-of-concept to active exploitation:
- February 2021 — Birsan's original dependency confusion research explicitly named NuGet, alongside npm, PyPI, and RubyGems, as a vulnerable package manager subject to the same default-resolution flaw, netting over $130,000 in bug bounties across affected organizations.
- November 2021–2022 — Following industry pressure, Microsoft's NuGet team began rolling out Package Source Mapping, a feature that lets teams explicitly pin which package IDs (or ID patterns) are allowed to resolve from which feed — the most direct structural mitigation available to date. It shipped broadly with NuGet 6.2 but adoption has remained low because it requires manual, per-organization configuration that many teams never complete.
- 2022–2023 — Security researchers at JFrog and other firms documented a steady stream of malicious and typosquatted NuGet packages, including packages that executed PowerShell payloads on install via
install.ps1scripts — a NuGet-specific mechanism not present in most other ecosystems, which gives attackers code execution at package-install time rather than just at runtime. - October 2023 — ReversingLabs researchers disclosed a malicious NuGet package,
SqzrFramework480, that impersonated software associated with industrial control tooling and contained code designed to capture screenshots and exfiltrate data from developer machines — a rare documented case of a supply chain attack via NuGet with an apparent industrial/OT targeting angle. - 2024–2025 — Continued reporting from the package-security research community has flagged clusters of NuGet packages using automated typosquatting against high-download libraries (
Newtonsoft.Json,Serilog,AutoMapperlook-alikes), alongside renewed warnings that many enterprise NuGet feed configurations still default to public-fallback resolution.
Taken together, these incidents show a consistent pattern: NuGet's attack surface hasn't required a single dramatic breach to matter — it has accumulated risk through structural defaults, low mitigation adoption, and an ecosystem-specific install-script feature that gives attackers more leverage per successful confusion attack than in registries without that capability.
Why NuGet Remains Structurally Exposed
Three factors keep NuGet dependency confusion risk elevated relative to where mitigation maturity should be four-plus years after the issue was first disclosed publicly:
Default trust in public fallback. Many enterprise nuget.config files still list nuget.org as a package source alongside internal feeds without scoping which names belong to which source. Unless Package Source Mapping is explicitly configured, resolution defaults to whichever feed offers a satisfying, higher-versioned match.
Install-time script execution. NuGet's support for install.ps1 and init.ps1 PowerShell scripts, executed automatically when a package is installed or restored, means a successful confusion attack can achieve code execution on a developer workstation or CI runner the moment dotnet restore or nuget install runs — before any application code is ever built or deployed.
Low observability into internal package naming exposure. Most organizations have no systematic way of knowing which internal package names have leaked into public view via GitHub, Stack Overflow questions, error logs, or SBOM artifacts shared with third parties — meaning the size of their actual exposure is usually unknown until an incident or a proactive audit surfaces it.
What Effective Mitigation Requires
Point fixes exist — Package Source Mapping being the most direct — but they only work if applied consistently across every internal repository, build pipeline, and developer machine, and if kept in sync as internal package inventories change. In practice, most enterprise NuGet estates are large, decentralized, and maintained by many teams, which makes manual, config-file-level mitigation fragile at scale. What's needed is continuous visibility: knowing every internal package name in use, whether a same-named or confusingly similar package exists publicly, whether any feed configuration allows ambiguous resolution, and whether a newly published public package actually gets pulled into a build before it causes damage.
How Safeguard Helps
Safeguard gives .NET and mixed-language organizations the visibility and control that manual NuGet configuration hygiene can't guarantee at scale. Our platform ingests and generates SBOMs across your NuGet estate, continuously cross-referencing internal package names against nuget.org to flag confusion and typosquatting exposure before an attacker can exploit it. Reachability analysis goes a step further, determining whether a flagged or newly resolved package is actually invoked in your application's call paths — so security teams can prioritize the handful of confusable packages that matter over the noise of theoretical exposure. Griffin, Safeguard's AI-driven security agent, correlates feed configuration, package resolution behavior, and known malicious-package intelligence to surface dependency confusion risk in context, not as an isolated alert. And when a fix is available — whether that's adding a Package Source Mapping entry, pinning a package to an internal source, or removing a squatted dependency — Safeguard can open an auto-fix pull request directly, turning a structural NuGet weakness into a reviewed, one-click remediation.