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 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
Now that pip provisionally supports installing from pylock.toml using the
--requirements/-r flag, it's possible to avoid a Time-of-check/Time-of-use
(TOC/TOU) race by first generating a lock file, verifying that lock file using
--lock-file/-L, and then installing from that same lock file.
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:
Metadata
Release files for pypi-verify-now 0.8.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| pypi_verify_now-0.8.1.tar.gz | 7.9 kB | With provenance | Details for pypi_verify_now-0.8.1.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| pypi_verify_now-0.8.1-py3-none-any.whl | Python 3 | none | any | Details for pypi_verify_now-0.8.1-py3-none-any.whl |
Total release size: 14.3 kB
Release files / pypi_verify_now-0.8.1.tar.gz
| Download URL | pypi_verify_now-0.8.1.tar.gz |
|---|---|
| Size | 7.9 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
9f36335b1ec41cb4bca8f253af030a341fd8a6efc295ffb761de8f5c77cd302b
|
|
BLAKE2b-256 checksum How to use checksums |
fdc0d44ad531c5e9a5e7556a360cef882f859da3d21886190e903832658a5716
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.2.0 CPython/3.14.5
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitLab CI/CD, verified by PyPI on Jun 17, 2026.
Transparency logRelease files / pypi_verify_now-0.8.1-py3-none-any.whl
| Download URL | pypi_verify_now-0.8.1-py3-none-any.whl |
|---|---|
| Size | 6.3 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
0fd11dd3991fdeae7e57baa906bb166c91c767590c7abba22678213908e68a1a
|
|
BLAKE2b-256 checksum How to use checksums |
144f04d7aef7c49df0527c56376294283a1959c95ee8ed02c86c17691dd74d50
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.2.0 CPython/3.14.5
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitLab CI/CD, verified by PyPI on Jun 17, 2026.
Transparency logSecurity for pypi-verify-now 0.8.1
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
Full provenance
All 2 files in this release have been uploaded with provenance metadata.
Attestation for pypi_verify_now-0.8.1.tar.gz
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitLab CI/CD, verified by PyPI on Jun 17, 2026.
Transparency logA note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.