flawopen.com/Reference/Dependency Confusion
Dependency Confusion: How Package-Source Mix-ups Happen
Imagine your team orders a component from a supplier catalog, but two suppliers use the same product name. If the ordering rules do not identify which supplier is authoritative, the build may receive an unintended component. Dependency confusion is this source-selection failure in software packages: a build resolves a package name from a registry or namespace the organization did not intend to trust.
How dependency confusion happens
The exact behavior depends on the package manager and its configuration. A concrete case is pip: its documentation warns that combining a private --index-url with public --extra-index-url can allow a same-name public package to be selected. npm instead chooses a registry based on package scope or its configured default; it does not universally compare a private and public version and pick the larger one. The common root cause is ambiguous source policy: a build can resolve a dependency name from a source outside the organization’s intended trust boundary. If the resolved package is installed and its lifecycle/build scripts are enabled, those scripts execute in the build environment with that job’s available permissions.
[global]
index-url = https://packages.example.internal/simple
extra-index-url = https://pypi.org/simple
corp-auth-utils
@corp:registry=https://packages.example.internal/repository/npm/
{
"dependencies": {
"@corp/billing-engine": "1.2.0"
}
}
A dependency-confusion failure path
- 1An internal package name or namespace becomes discoverable outside the organization.
- 2A public registry contains a package with the same unscoped name, or the configured source policy permits that registry to satisfy the request.
- 3The resolver selects the unintended package source; the lockfile or review process may not catch the substitution if the lock is absent, regenerated, or trusted without inspection.
- 4If installation or build scripts are enabled, package code runs with the build job’s permissions. Impact depends on credentials, network access, and isolation; root execution is not inherent to this attack class.
Defensive engineering controls
- ✓Make source policy explicit: Use organization-owned scopes or namespaces where supported, route them to the intended registry, and prevent fallback to public sources for private names. For Python, avoid combining a private index with
--extra-index-urlfor private packages; use a controlled proxy or a single authoritative index. - ✓Control namespace ownership: Reserve or claim organization names on registries when supported, but do not treat name reservation as a substitute for resolver policy. Inventory internal names and monitor for public collisions.
- ✓Review and enforce lockfiles: Commit the lockfile and use the package manager’s frozen/CI install mode (for npm,
npm ci). Review changes to package names, resolved registry URLs, versions, and integrity values. A lockfile improves repeatability; it does not prove that the selected source is the intended publisher. - ✓Constrain build execution: Disable dependency lifecycle scripts where the project can function without them, and review exceptions. Give build jobs short-lived, least-privilege credentials; isolate them from production secrets and limit network egress.