Verifies pypi-attestations in a build pipeline
Project description
pypi-verify-now
This is a trust-on-first-use (TOFU) solution to the problem of verifying the build provenance of packages downloaded from PyPI, that is usable now for brave and/or impatient users that want to experiment with this immediately or even sooner.
Pre-abandonware
This tool is intended to never reach version 1.0. Instead, whenever Pip starts verifying signatures client-side, this tool will go to version 99.9 and be end-of-lifed.
How-to and security considerations
First run the tool in TOFU mode with arguments supported by pip lock -- the
arguments will be passed on as-is to pip-lock, so you can use -r to process
a requirements file, or --group to verify packages specified by a PEP735
dependency group, or any other mechanism supported by pip as long as it
generates a lock file:
TOFU=1 python -m pypi_verify_now --group build
This generates a file called .provenance.txt, which for each package lists the
repository URL that's expected to have signed it. If a package is signed, but its
originating repository URL is not recorded here, the package signature will not
be considered valid. The file is expected to be committed to source control, and
any changes to be reviewed.
After this, for example in a CI pipeline, create a build step that runs without TOFU:
python -m pypi_verify_now --group build
If this ever fails the build, one of the following things happened:
- A package is being signed from a different URL
- A package has started uploading signatures to PyPI, but the repo URL isn't yet known
- A package is no longer signed, but was expected to be signed in
.provenance.txt - A malicious package was somehow uploaded to PyPI
All of these will fail the build. The .provenance.txt will need to be updated
in some way. Removing failing packages from .provenance.txt and re-running
with TOFU=1 will make the tool happy, but ONLY the user can review the
validity of the resulting changes to .provenance.txt. If this manual review
doesn't happen, I'm don't think the resulting security posture is meaningfully
better.
Configuration
Three settings can be configured through passing in environment variables:
- TOFU=1 (default 0): set to '1' to generate an updated version of the provenance file
- STRICT=1 (default 0): set to '1' to fail if any package is missing a signature (unlikely to be usable currently in 2025Q3)
- FILENAME=... (default .provenance.txt): path to file where for each dependency originating repository URL is configured
Security warning
For my use case, today, I think this is good enough, or at least better than no signature verification. My understanding of security, OIDC and SigStore is more than zero, but still limited. See the license text; "PROVIDED AS-IS" etc.
I expect the PyPA/pip developers to spend a lot more time thinking about this problem and tackle nuances that I haven't thought about, and that this process understandably takes longer than the few hours I spent banging out this script, so it's advisable to evaluate risks accordingly.
TOC/TOU
There's a Time-of-check/Time-of-use (TOC/TOU) vulnerability. In the small window between TOC and TOU, this tool could verify one set of packages, and because Pip can't (yet) install from a lock file, Pip will do the dependency resolution again, possibly installing a slightly different set of packages.
Links
- https://docs.pypi.org/trusted-publishers/
- https://docs.pypi.org/attestations/
- https://peps.python.org/pep-0740/ - PEP 740 - Index support for digital attestations
- https://peps.python.org/pep-0751/ - PEP 751 - A file format to record Python dependencies for installation reproducibility
- https://discuss.python.org/t/ideas-for-client-side-package-provenance-checks/64679
- https://blog.trailofbits.com/2024/11/14/attestations-a-new-generation-of-signatures-on-pypi/
- https://docs.pypi.org/api/integrity/
Talk from PyCon 2025:
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file pypi_verify_now-0.6.tar.gz.
File metadata
- Download URL: pypi_verify_now-0.6.tar.gz
- Upload date:
- Size: 7.8 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.12.11
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b60dfb1731cd0712ea1db64c825a253cf7b41746b45d4b09a9d7a9e510451c1c
|
|
| MD5 |
0f25760ac4e7fbd96e899604dcfb0344
|
|
| BLAKE2b-256 |
4ed61bc7b9f54f432fac000feb34165ddf8d0f473e0e77b0792e8dacbd70f064
|
Provenance
The following attestation bundles were made for pypi_verify_now-0.6.tar.gz:
Publisher:
gitlab-ci.yml on j0057-git/python/pypi-verify-now
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
pypi_verify_now-0.6.tar.gz -
Subject digest:
b60dfb1731cd0712ea1db64c825a253cf7b41746b45d4b09a9d7a9e510451c1c - Sigstore transparency entry: 433949378
- Sigstore integration time:
-
Permalink:
j0057-git/python/pypi-verify-now@8ed90148497c64bd2afd360aaa0b74d3c0482896 -
Branch / Tag:
refs/tags/0.6 - Owner: https://gitlab.com/j0057-git/python
-
Access:
public
-
Token Issuer:
https://gitlab.com -
Runner Environment:
gitlab-hosted -
Publication workflow:
gitlab-ci.yml@8ed90148497c64bd2afd360aaa0b74d3c0482896 -
Trigger Event:
push
-
Statement type:
File details
Details for the file pypi_verify_now-0.6-py3-none-any.whl.
File metadata
- Download URL: pypi_verify_now-0.6-py3-none-any.whl
- Upload date:
- Size: 6.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.12.11
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
2d6964f810fe16f5743e684ddcd59d3daa4b57dd04e06cf49bbfd167e78e4fd0
|
|
| MD5 |
ea72f45aad2bb29242045e058d732465
|
|
| BLAKE2b-256 |
f3a6690b74130cc4cc5dd2e4243645fc052620a3d98207b8696ca2429f892e7c
|
Provenance
The following attestation bundles were made for pypi_verify_now-0.6-py3-none-any.whl:
Publisher:
gitlab-ci.yml on j0057-git/python/pypi-verify-now
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
pypi_verify_now-0.6-py3-none-any.whl -
Subject digest:
2d6964f810fe16f5743e684ddcd59d3daa4b57dd04e06cf49bbfd167e78e4fd0 - Sigstore transparency entry: 433949346
- Sigstore integration time:
-
Permalink:
j0057-git/python/pypi-verify-now@8ed90148497c64bd2afd360aaa0b74d3c0482896 -
Branch / Tag:
refs/tags/0.6 - Owner: https://gitlab.com/j0057-git/python
-
Access:
public
-
Token Issuer:
https://gitlab.com -
Runner Environment:
gitlab-hosted -
Publication workflow:
gitlab-ci.yml@8ed90148497c64bd2afd360aaa0b74d3c0482896 -
Trigger Event:
push
-
Statement type: