
Dependency confusion and trust boundaries in modern builds

Dependency confusion is a software supply chain weakness that arises from how package managers resolve dependencies across multiple sources.
It does not rely on complex exploits. It relies on normal dependency resolution.
If a build resolves from both private and public registries, and a public package shares the same name as an internal dependency, the public package may be selected. That is sufficient to introduce unintended code into a build.
Modern dependency trees often include extensive transitive dependencies, increasing the number of automatic resolution decisions made during builds.
The issue was widely documented in 2021 when researchers demonstrated it against more than 35 large organizations by publishing public packages that matched internal names. Since then, dependency confusion has remained a known and preventable risk in modern build systems.
Where risk appears in practice
Modern builds commonly blend:
- Internal packages
- Public open source dependencies
- Upstream proxies
- Cached artifacts
If resolution rules are not explicit, package managers make decisions on your behalf.
Different ecosystems provide different structural protections and different pitfalls.
Ecosystem specific considerations
Python
PyPI operates on a flat global namespace. There are no built-in organizational scopes and no domain bound identifiers. Package names are globally unique and first come, first served.
This means internal package names, for example acme utils or internal ml core, are structurally indistinguishable from public ones unless additional controls are applied.
Python projects frequently configure multiple indexes. It is common to see:
- Internal private mirrors
- Vendor-hosted repositories such as PyTorch wheel indexes for CUDA builds
- Regional mirrors
- Index url combined with extra index url
Python tooling such as pip, uv, and Poetry evaluates candidate versions across configured sources. If the same package name exists in more than one index, the resolver may select the highest compatible version, regardless of origin.
Real-world incidents demonstrate this behavior. In 2022, a malicious package mimicking a PyTorch dependency was published to PyPI and installed via pip resolution during nightly builds, leading to data exfiltration before detection.
Without explicit trust boundaries or source mapping, this multi index behavior introduces ambiguity. If an internal package name is exposed and a higher version appears on a public index included in resolution, the public package may be selected.
Python’s flat namespace model, combined with common multi index configurations, makes careful source control particularly important.
npm
npm supports scoped packages using the @org/package format. Once registered, a scope is controlled by that organization.
However, unregistered scopes remain claimable. If an organization uses scoped internal packages but has not reserved the scope publicly, an attacker could register it and publish similarly named packages, for example @org/app. A configuration mistake in development or CI could then result in the malicious package being resolved and executed, including via lifecycle hooks such as preinstall.
Unscoped internal package names carry exposure similar to Python.
Maven
Maven Central uses domain-based groupId verification, providing stronger ownership guarantees when correctly configured.
However, inconsistent repository usage or additional repositories can reintroduce ambiguity in resolution order if trust boundaries are not clearly defined.
NuGet
While NuGet supports ID prefix reservation to prevent public name squatting, resolution ambiguity can still arise if multiple feeds are configured.
Key safeguards include:
- ID prefix reservationReserve your organization’s package ID prefix on nuget.org to prevent public impersonation.
- Package Source Mapping Use NuGet 6+ source mapping to bind specific package IDs or prefixes to a single trusted feed.
- Strict nuget.config configurationClear default feeds and explicitly define approved sources to prevent unintended restores.
- Signature enforcementNuGet repository signing using X.509 certificates. When signature verification is enforced in the NuGet or .NET CLI, consumers can verify that a package originated from the expected repository and has not been tampered with.
Docker
Docker Hub differs from language ecosystems because image references are typically registry qualified, making classic multi-source confusion less common.
However, related risks remain:
- Implicit Docker Hub fallback when no registry is specified
- Unregistered namespace squatting
- Mutable tags such as latest
These are mitigated through fully qualified image references, namespace reservation, digest pinning using SHA256, and image signing.
A layered mitigation approach
Preventing dependency confusion does not require dramatic changes to developer workflows. It requires clear trust boundaries in how dependencies are resolved.
In practice, this is implemented through an internal artifact repository that controls how dependencies are proxied, cached, and resolved.
Key elements include:
- Centralizing dependency resolution
- Defining explicit upstream trust
- Controlling namespace ownership
- Using lockfiles and reproducible builds
- Enforcing artifact signing and verification
1. Central artifact repository
Route all builds through a central artifact repository that acts as the single source of truth for dependencies. Public packages should be proxied and cached internally rather than resolved directly from the internet.
2. Define upstream trust
Explicitly distinguish between trusted and untrusted sources.
Cloudsmith provides upstream trust controls that allow repositories to designate upstream sources accordingly and control how packages are blended during resolution. If a package exists in a trusted source, it cannot be overridden by an untrusted one.
Cloudsmith’s Upstream Trust currently supports:
- Python
- Maven
- npm
Support for additional ecosystems is expanding. In addition to source trust controls, policy enforcement provides another layer of protection. Cloudsmith’s Enterprise Policy Manager allows organizations to define rules around what packages are permitted, including conditions based on vulnerability data, malware data, version constraints, or upstream origin. This enables teams to combine resolution boundaries with policy-based controls.
3. Reserve namespaces
Where supported:
- Use npm scopes
- Reserve NuGet ID prefixes
- Use domain based Maven group IDs
Namespace ownership significantly reduces collision risk.
4. Use lockfiles
Lockfiles improve determinism, traceability, and visibility into unexpected changes. They do not eliminate dependency confusion, but they reduce instability and make tampering easier to detect.
5. Require signing
Signing adds cryptographic integrity to artifacts.
Cloudsmith signs hosted packages by default. Cloudsmith supports both native and non-native signing across package formats, including native signing for Docker, NuGet, and Swift. Signature validation workflows in supported ecosystems provide an additional verification layer if substitution is attempted.
Signing strengthens integrity guarantees but does not replace resolution controls.
Conclusion
Dependency confusion is not a sophisticated exploit. It is a consequence of ambiguous resolution behavior across multiple sources.
Preventing it requires:
- A central artifact repository serving as the single source of truth for dependencies
- Explicit upstream trust boundaries
- Namespace ownership
- Lockfiles and reproducible builds
- Artifact signing and verification
Clear boundaries remove ambiguity. Removing ambiguity removes the attack path.
Stop leaving your build integrity to chance. Book a demo today to see how Cloudsmith's enterprise-grade repository controls can remove ambiguity and harden your delivery process.
More articles


Why cloud migrations are the best time to re-evaluate your artifact management

AI artifacts: The new software supply chain blind spot

Access control & permissions for multi-format repositories

The true cost of legacy artifact management

