pip does not rank package indexes. When you add an extra index, pip searches all of them with no priority, so a package with the same name on a public index can be chosen over your private or vendor build. The pip documentation calls this approach unsafe because of dependency confusion.
Why ML teams hit this
ML projects often need packages that are not on the default index in the build you want: GPU specific wheels, an internal feature library, a patched fork. The usual fix is an extra index URL in the install command or the requirements file.
That feels harmless. It is the exact setup that creates the problem.
What pip documents
The pip install reference describes the index URL option as the base index, which defaults to the public one, and the extra index URL option as additional locations to search. It says there is no priority in the locations that are searched, and it warns that using the extra option to find packages that are not in the main repository is unsafe because of dependency confusion.
Put plainly: if an attacker publishes a package on the public index using the same name as your internal one, pip may consider it, and a higher version number can win.
How the attack idea works
- Your team installs an internal package called, say, a feature library, from a private index.
- A requirements file lists the public index as the base and the private one as extra.
- Someone registers the same name publicly with a very high version.
- A fresh install sees two candidates, and picks the newest.
The code in the winning package then runs on your build machine or in your training job.
Ways to reduce the risk
| Approach | Notes |
|---|---|
| Use a single internal index that proxies the public one | You decide which names resolve where |
| Reserve your internal names on the public index | A cheap placeholder blocks a squatter |
| Pin exact versions and hashes | A surprise package fails the hash check |
| Install from a direct URL or path for special wheels | Removes name based lookup for those packages |
| Review new indexes in code review | Treat index lines as security relevant |
Our guide to pip hash checking shows how pinned hashes make a swapped package fail loudly.
A quick audit you can run today
grep -rn "extra-index-url" . --include="*.txt" --include="*.toml" --include="*.cfg" --include="Dockerfile*" --include="*.yml"
For each hit, ask: which packages come from this index, and could a public package with the same name exist?
Where this fits in your policy
Write a rule that says every index must be named, owned and reviewed. Keep the list short. Add a check in CI that fails when a new index appears without approval.
Where Safeguard fits
Safeguard's SBOM and dependency scanning show you exactly which packages and versions an ML project resolves to, and policy gates in pull requests can flag changes. Try a free scan at gold.safeguard.sh/scan.
Quick check
Is the extra index always unsafe?
pip's warning is about using it to find packages that are not in the main repository. If every name you take from it is guaranteed unique and controlled, the risk is lower, but a single trusted index is cleaner.
Does a pinned version fix it?
An exact pin helps, and adding hashes makes a swapped package fail the install.
Sources
Last reviewed: 19 October 2026.