Open Source Security

PyPI Package Namespace Governance

PyPI's flat global namespace is one of Python packaging's oldest design decisions. How it's governed today, where the tension points are, and what the PEP 752 debate means for the future.

Nayan Dey
Senior Security Engineer
6 min read

PyPI is one of the last remaining major package registries with a single, flat, globally shared namespace. npm has scoped packages, crates.io has an even stricter flat namespace but with a much smaller surface, Maven Central uses reverse-DNS groupIds, and Go treats import paths as identities that are already namespaced by the hosting domain. PyPI, stubbornly, has requests and boto3 and numpy living next to requessts and bot0-3 in the same dictionary. This design decision is at the center of a lot of the ecosystem's current security conversations, and the governance model around it is more intricate than it looks.

The Rules as They Stand

The canonical governance document for PyPI package names is PEP 541, "Package Index Name Retention," accepted in March 2020 after several years of informal practice. PEP 541 codified a small set of grounds on which PyPI administrators will intervene to transfer, rename, or reclaim a package name.

Those grounds are: the original owner has abandoned the project and has not responded to contact attempts over a defined period; the name was registered in violation of the PyPI Acceptable Use Policy, for example as a placeholder to extract payment from a trademark holder; the project contains malware or other actively harmful content; or the original owner has voluntarily agreed to transfer.

PEP 541 is deliberately conservative. It does not grant name preference to organizations over individuals, it does not treat "I want this name" as a valid claim, and it does not provide a fast-track for trademark holders outside of specific documented circumstances. The admins have held this line consistently in the public disputes that have shown up on the pypi-announce and distutils-sig mailing lists since 2020.

Why Typosquatting Is a Namespace Problem

In a flat namespace, reqests, requsts, request, and reqeuests are all valid distinct names, and a user who mistypes the real requests package has a non-trivial chance of landing on one of them. The 2017 research paper "Typosquatting and Combosquatting Attacks on the Python Ecosystem" by Vaidya et al. (published at ESORICS) documented dozens of live typosquats against popular PyPI packages. Subsequent work by Sonatype, Snyk, and the Checkmarx research team has shown that typosquatting persists as a significant category of PyPI attacks — 2023's report from Phylum ("State of the Software Supply Chain," November 2023) identified 1,490 typosquat packages removed from PyPI across the year.

PyPI's response has layered:

Warehouse implements name normalization under PEP 503, so Django, django, and DJANGO all resolve to the same name. Warehouse also applies a confusability check at registration time for new names that are too close to existing popular names, rejecting them with a helpful error. And PyPI's admin team reviews reports of live typosquats and removes them under the malware provisions of PEP 541.

But the core design — a flat namespace where requesrs is as valid a name as any — remains, and the defense is necessarily reactive.

Organizations Change the Surface, Slightly

The July 2023 launch of Organization Accounts added an organizational identity layer on top of the flat name namespace (PyPI blog, "Introducing Organizations on PyPI," 25 July 2023). An organization owns a set of packages, its members can publish to those packages, and its identity is visible on each project's PyPI page. What organizations do not do — and this is the crucial part — is namespace the package names themselves. @openai/openai-python is an npm-style scoped name; PyPI's equivalent is just openai, owned by the OpenAI organization but indistinguishable in the name string from any other project.

This means organizations are useful for publishing and governance within a group, but they do not change the typosquatting picture. An attacker who registers opneai is not blocked by the existence of the OpenAI organization.

PEP 752: The Namespace Proposal

The most active governance conversation as of early 2024 is PEP 752, "Package Repository Namespaces," drafted by Ofek Lev and others in late 2023. PEP 752 proposes adding first-class namespaced package names to PyPI, formatted as namespace-project or similar, where the namespace is owned by an organization or user account that can reserve names beneath it.

The proposal aims to solve three problems: trademark holders who want reliable ownership of a name they use elsewhere; security-conscious organizations who want to publish under a verifiable prefix; and typosquatting defense by making the real package's name syntactically distinct from the squatter's.

The draft has been the subject of extensive discussion on discuss.python.org through the first quarter of 2024. Objections center on backward compatibility, user confusion about which variant of a name is "real," and the question of whether namespacing actually reduces typosquatting or just moves it one level down (an attacker now squats acme-reqests instead of reqests). As of this writing in April 2024, the PEP is in draft and the Packaging Steering Council has not yet taken a position.

Reserved and Prohibited Names

A less visible part of namespace governance is the list of reserved names Warehouse refuses to register. This includes Python standard library module names (you cannot publish a sys or os package to PyPI), historically problematic names, and names that collide with internal Warehouse routing. Dustin Ingram has spoken publicly about the ongoing maintenance of this list — it's a security surface of its own, and names get added as new conflicts are discovered.

The dependency-confusion class of attacks (popularized by Alex Birsan's February 2021 research, "Dependency Confusion: How I Hacked Into Apple, Microsoft and Dozens of Other Companies") exploits exactly this gap. Internal package names that exist only in a private registry can be registered by an attacker on public PyPI, and installers that don't pin their index will fetch the attacker's version. The reserved-name list doesn't help here because the names are organization-specific.

What This Means for Publishers

For an organization shipping Python packages in 2024, the practical namespace guidance is narrower than the governance question suggests:

Register your real package names early, ideally through an organization account. Register obvious typo variants if the package is prominent enough to attract squatters — many well-known projects do this defensively. Publish internal package names to PyPI as empty placeholder packages to block dependency-confusion squatting, even if you have no intention of distributing them publicly. And watch PEP 752's progression; if it lands, your namespace reservations will want to be updated.

How Safeguard Helps

Safeguard tracks the PyPI packages your projects install and flags names that are lexically close to established popular packages, using published typosquatting heuristics plus curated allow and deny lists. When a new transitive dependency resolves to a name that is one character away from a package you actually use, Safeguard raises it in your findings feed with the resolution path so you can decide whether it's legitimate. For organizations publishing to PyPI, Safeguard inventories your namespace footprint and alerts when a new package is registered under a name confusingly similar to one you own.

Never miss an update

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