PyPI, Python's package index, operates on a flat namespace. There are no scopes, no organizations, no verified publishers in the package name itself. Anyone can upload any package name that is not already taken. This design decision, inherited from Python's early days, has become a significant supply chain security problem.
Unlike npm (which has scoped packages like @angular/core) or Maven (which uses reverse domain names like org.apache.commons), PyPI names are first-come, first-served. The package requests belongs to whoever registered it first. There is no @python/requests or org.python.requests to distinguish official packages from imposters.
How Namespace Squatting Works
Namespace squatting on PyPI takes several forms:
Typosquatting. Registering names that are common misspellings of popular packages. Examples include reqeusts instead of requests, beautifulsoup instead of beautifulsoup4, or python-dateutil vs dateutil. Researchers have found hundreds of typosquatting packages on PyPI at any given time.
Name confusion. Registering names that sound like they could be official packages for popular frameworks. A package named django-security-middleware sounds like it could be an official Django project, even though anyone can register it.
Abandoned name reclamation. When a popular package is removed from PyPI, the name becomes available. Attackers monitor for popular package deletions and immediately re-register the name with malicious code.
Internal package name collision. Companies often have internal packages with names like company-utils or auth-library. If those names are not registered on PyPI and a developer misconfigures pip to check PyPI before the internal index, an attacker can register the name on PyPI and hijack the installation.
The Scale of the Problem
In 2022, researchers from Checkmarx identified over 400 malicious PyPI packages in a single campaign that used namespace squatting. The packages targeted popular libraries and frameworks, and many included info-stealer malware that harvested credentials and cryptocurrency wallets.
PyPI processes millions of downloads per day. Even a short-lived malicious package with a convincing name can accumulate thousands of installations before detection. The ctx package incident in 2022 demonstrated this when an attacker took over a legitimately abandoned package and pushed a version that stole environment variables.
Why Python Is Particularly Vulnerable
Several factors make the Python ecosystem especially susceptible:
pip installs execute code. By default, pip install runs setup.py, which is arbitrary Python code. A malicious setup.py can execute payloads during installation, before the developer ever imports the package.
No built-in verification. pip does not verify package authenticity beyond checking the name and version against the index. There is no signature verification by default.
Transitive dependencies compound risk. A single pip install can pull in dozens of transitive dependencies. An attacker does not need to impersonate the top-level package -- a convincingly named transitive dependency works just as well.
Requirements files lack context. A requirements.txt listing requests==2.28.0 provides no indication of where the package should come from. There is no registry URL, no publisher, no checksum by default.
Defensive Strategies
Hash pinning in requirements. Use pip install --require-hashes with pinned hashes in your requirements file. This ensures that even if a package name is hijacked, the installation will fail if the content does not match the expected hash.
requests==2.28.0 --hash=sha256:7c5599b102...
Use pip-compile with hashes. The pip-tools package can generate requirements files with hashes automatically, making hash pinning practical for large dependency trees.
Private index configuration. Configure pip to use a private index with --index-url for internal packages and --extra-index-url only for public packages. Better yet, use a proxy that mirrors approved PyPI packages.
PEP 708 and Trusted Publishers. PyPI has introduced Trusted Publishers, which link package uploads to specific CI/CD workflows (GitHub Actions, GitLab CI). While this does not prevent namespace squatting, it provides a verified chain of custody for packages that opt in.
Namespace reservation. If your organization has internal packages, register those names on PyPI even if you do not plan to publish publicly. This prevents attackers from claiming those names.
Monitoring and Detection
Watch for new packages with similar names. Services that monitor PyPI can alert you when packages with names similar to your dependencies are published. This early warning can catch typosquatting campaigns before your developers are affected.
Audit installation sources. In CI/CD, log the full download URLs for every package installed. Any package coming from an unexpected source is a red flag.
Check package metadata. Legitimate packages typically have a project URL, author information, description, and version history. Newly registered packages with minimal metadata and similar names to popular packages are suspicious.
Verify download counts. A package claiming to be a utility for a major framework but showing only a handful of downloads is likely not what it claims to be.
The Path Forward
The Python packaging community is working on several improvements. PEP 708 introduces metadata for alternate repository discovery. Trusted Publishers, already available on PyPI, link package uploads to verified CI/CD sources. There are ongoing discussions about introducing namespaces or scopes to PyPI, though backwards compatibility makes this challenging.
Until these improvements are universally adopted, the burden falls on development teams to implement their own defenses. The combination of hash pinning, private registries, and active monitoring provides a strong defensive posture against namespace squatting.
How Safeguard.sh Helps
Safeguard.sh monitors your Python dependency chain for namespace squatting and typosquatting threats. The platform validates package sources, tracks changes in package ownership or metadata, and flags suspicious packages that appear similar to your declared dependencies. With automated SBOM generation and continuous dependency analysis, Safeguard.sh helps teams detect and respond to PyPI namespace attacks before compromised packages reach production environments.