Skip to content

PyPI

Python Package Index

The Python package registry that pip installs from by default.

  • Registries

About

PyPI is the public registry for Python packages, and pip installs from it by default. Web apps, data science and AI code all lean on it heavily. Anyone can publish there, and names go to whoever claims them first, so a name alone does not show who wrote the code.

A package published as source can run its build code during pip install, with the rights of whoever installs it. Everything else runs inside the app whenever it imports the package.

If It Is Malicious

If a PyPI package is malicious, it runs inside a Python app with the app's rights, on every developer laptop and build server that installs it.

Its code runs inside these technologies.

See It in the Stack

Examples

These are well-known names from PyPI, written as you would meet them in an inventory, an alert or a lockfile, the file that records every version a build installed.

requests
The usual way Python code makes HTTP calls.
urllib3
The HTTP library under requests, installed without anyone asking for it.
django
The Django framework, installed with pip like any other package.
numpy
Number crunching that much data science and AI code relies on.
boto3
The AWS SDK for Python.

How Bad Code Gets In

These are the ways bad code can reach your systems through PyPI. None of them needs a flaw in your own code, so outside code needs checking as much as your own.

  • A package named like a popular one catches mistyped installs.
  • A public package shadows one from a private or extra index, as happened to PyTorch.
  • A maintainer's account or token is stolen and a bad release is uploaded.
  • A project's own release workflow is abused, so its real pipeline publishes bad code.

How to Check

These checks show what came from PyPI, whether a known bad version is in use, and how to keep one out next time.

  • Pin exact versions with hashes, and install with pip's hash checking turned on.
  • Run pip-audit, which checks your requirements against known advisories.
  • Use one index, or a private mirror of PyPI, rather than adding an extra index beside it.
  • Check a release's attestations on PyPI, which name the repository and workflow that published it.

Well-Known Incidents

Each incident below is a real case, told at the level of its public advisory. The tag says how the bad code got in, and the link opens the primary source.

  • Typosquat2017

    Typosquats on PyPI

    Slovakia's National Security Authority found ten PyPI packages with look-alike names, such as urlib3 for urllib3, that ran extra code when installed.

    Reach Anyone who mistyped a name ran the extra code, which sent the user name and the machine's name back. PyPI removed the packages.

    Affectedurlib3setup-toolsdjango-server

    Source: sk-cert.sk (opens in a new tab)
  • Dependency Confusion2022

    PyTorch torchtriton

    A package on PyPI took the name of a dependency that PyTorch nightly builds fetched from PyTorch's own index, and pip installed the PyPI copy instead.

    Reach Linux machines that installed PyTorch nightly builds with pip between 25 and 30 December 2022 got the fake package. Once code imported it, it sent system details and files, SSH keys included, to the attacker.

    Affectedtorchtriton

    Source: pytorch.org (opens in a new tab)
  • Compromised Build or Release2024

    Ultralytics

    Attackers abused the project's own GitHub Actions workflow, so its normal release process built and published versions that carried a cryptominer. Two more followed through a leftover publishing token.

    Reach Anyone who installed or upgraded the popular AI vision library in those days got the miner. The first two bad releases came from the real pipeline, so their provenance looked like any genuine release's.

    Affectedultralytics

    Source: blog.pypi.org (opens in a new tab)

In Common Stacks

These common stacks take code from PyPI. Open one to see where that code sits among its layers and who runs each one.

Sources

Product names and logos are trademarks of their owners, shown only to name each product, with no endorsement implied. npm is a registered trademark of npm, Inc.

Apache, Apache HTTP Server, Tomcat and Log4j are trademarks of the Apache Software Foundation. Node.js® is a registered trademark of the OpenJS Foundation, and Kubernetes® of LF Projects, LLC.

Linux® is the registered trademark of Linus Torvalds in the U.S. and other countries. Docker and the Docker logo are trademarks or registered trademarks of Docker, Inc. in the United States and/or other countries.

MongoDB® is a registered trademark of MongoDB, Inc. Redis® is a registered trademark of Redis Ltd. Any rights therein are reserved to Redis Ltd.

PHP logo by Colin Viebrock, CC BY-SA 4.0 (opens in a new tab). Ruby logo © 2006 Yukihiro Matsumoto, CC BY-SA 2.5 (opens in a new tab). Tux by Larry Ewing, with Garrett LeSage and IFo Hancroft.

Puma logo © Evan Phoenix and contributors, CC BY-ND 3.0 (opens in a new tab). NuGet logo from NuGet's Media repository, CC BY 2.0 (opens in a new tab).

Gunicorn logo © Benoît Chesneau and Paul J. Davis, MIT licence for the Gunicorn logo (opens in a new tab). Packagist logo © 2011 Jordi Boggiano and Nils Adermann, MIT licence for the Packagist logo (opens in a new tab).

MIT Licence Notices for the Gunicorn and Packagist Logos

Gunicorn logo

2009-2024 (c) Benoît Chesneau <benoitc@gunicorn.org> 2009-2015 (c) Paul J. Davis <paul.joseph.davis@gmail.com>

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

Packagist logo

Copyright (c) 2011 Jordi Boggiano, Nils Adermann

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.