PyPI Upload Denial of Service
How popular Python projects could have been blocked from releasing new packages.
This is my first blog post on PyPI, the others are:
3: Distribution Confusion in PyPI
The Python Package Index (PyPI) is the main repository for Python packages. Anyone can create an account and upload packages to pypi.org. Those packages can then be installed via e.g. ‘pip install <package name>’. Pip will go to pypi.org/simple/<package name> and resolve which distribution (file) to download and install. The supported file formats are source distributions (‘.tar.gz’ and ‘.zip’) and binary distributions (‘.whl’).
When uploading a distribution to PyPI the file name has to be globally unique. PyPI has a check to see that there is no current file with that name (files can be deleted). It also checks that there has never been a file with that name.
Given that file names need to be globally unique, the intention is that each project has its own prefix to avoid collisions. The old check only verified that the normalized project name was a prefix of the normalized filename, e.g. that the file ‘requests-2.31.1.tar.gz’ started with ‘requests’ for project ‘requests’.
Finding examples of available project names that are prefixes of popular projects was not hard: ‘requ’ could be used to target ‘requests’. To construct a collision the whole filename would have to match, e.g. ‘requests-2.31.0.tar.gz’. The most important component is the version (the Wheel format has more components). Guessing future minor and major versions should not be too hard.
The impact would have been limited to preventing other projects from uploading specific distributions. The issue was fixed in #14027. Shout out to the PyPI maintainers for the quick patch!