Safeguard
Supply Chain•

How do you protect internal Python package names from lookalikes?

A decision guide for private Python package names: one index, a proxy, a public placeholder, or hashes. Pick by how your team installs packages.

Safeguard Security Team
4 min read

Make sure a public index can never answer for a name you own. The strongest options are to use a single index that serves both internal and public packages, or to register your internal names on the public index so nobody else can. Hash checking adds a final gate. Pick by how your builds are set up.

The risk in one paragraph

Python package indexes each have their own namespace. If a build can reach both a private index and a public one, and a name exists only privately, someone can publish that name publicly. PEP 708 describes this class of attack and cites a case where an internal package name was not claimed on PyPI and an attacker took it.

PEP 708 was rejected, so you cannot rely on a standard mechanism to settle it. See what happened to PEP 708.

Decision guide

Your situationBest fitWhy
Many teams, many private packagesOne proxy index that serves public and privateOne namespace you control, no second index to fall back to
A few internal packages, small teamRegister the names on the public indexCheap, removes the opening
Locked down productionHashes plus wheel only installsOnly recorded files install
Offline or regulated buildsWheelhouse with no index accessNo network lookups at all

The PEP's own guidance for pip users points the same direction: if you use a single remote repository there is nothing to do, and if you use several you should audit whether any dependency is served from more than one. For private projects with a public fallback, it suggests being explicit about where each dependency comes from, so a later registration of that name publicly cannot break or hijack your install. For project owners it suggests considering preemptively registering names in the other repositories that commonly sit alongside.

Steps

  1. List your internal package names. Include anything published only to a private index, even tools used by one team.
  2. Check each name publicly. Search the public index for the name. If it is free, decide whether to claim it. If it exists and is not yours, you have a problem: rename yours and audit where it was installed.
  3. Remove the second index where you can. Ask whether the public index is needed in that job at all.
  4. Add hashes for the production path, so a name collision cannot silently change which file installs. See pip require-hashes as the final gate.
  5. Name carefully. A consistent prefix makes collisions easier to spot in reviews, though a prefix is not protection by itself.
  6. Monitor. Alert when a public package appears with one of your internal names.

A note on placeholders

Registering a name publicly means publishing a project. Keep it clearly labelled as a placeholder, and check the public index's policies on empty or reserved projects before you do it. Do not put internal details in the description.

What not to do

Do not rely on index order. Pip does not treat extra indexes as a priority list: it considers candidates from all of them. See why extra-index-url is unsafe for private packages for why.

Make it routine

Add the name list to your repository, and a CI job that checks each name against the public index weekly. A new collision becomes a ticket, not an incident.

Safeguard's asset discovery and dependency scanning help you list which packages your projects actually use, and its policies can flag unknown names in a pull request. A free scan is available at gold.safeguard.sh/scan.

Quick check

Is a naming prefix enough protection?

No. It helps humans notice, but anyone can publish a name with your prefix on a public index.

Do I need this if I only use the public index?

No internal names are at risk then, but typos and lookalike names still are. Pin and review dependencies.

Sources

Last reviewed: 19 October 2026.

Never miss an update

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

Self-healing security runs on Safeguard.

Your first fix PR is minutes away.

No sales call required, even your agent can complete the purchase over MCP.