Package trust and provenance verification for PyPI consumers.
Project description
trustcheck
trustcheck is a Python package and CLI for evaluating the trust posture of PyPI releases before they are installed, promoted, or approved.
It combines PyPI metadata, vulnerability records, provenance availability, cryptographic attestation verification, Trusted Publisher identity hints, and repository matching into a single operator-friendly report.
What it checks
For a selected package version, trustcheck can:
- fetch project and release metadata from PyPI
- inspect declared repository URLs from project metadata
- retrieve provenance envelopes for each release artifact
- verify attestations against the downloaded artifact digest
- extract Trusted Publisher identity details such as repository and workflow
- compare expected repository input against declared and attested repository signals
- flag publisher repository and workflow drift against the previous release
- surface PyPI vulnerability records for the selected version
- emit a concise human-readable report or structured JSON
Installation
pip install trustcheck
Requirements:
- Python
>=3.10 - Network access to PyPI
CI currently runs on Python 3.12, and package classifiers only advertise versions covered by CI.
Quick start
Inspect the latest release:
trustcheck inspect requests
Inspect a specific version:
trustcheck inspect sampleproject --version 4.0.0
Require the release to match an expected source repository:
trustcheck inspect sampleproject \
--version 4.0.0 \
--expected-repo https://github.com/pypa/sampleproject
Show detailed per-file evidence:
trustcheck inspect sampleproject --version 4.0.0 --verbose
Emit JSON for another tool:
trustcheck inspect sampleproject --version 4.0.0 --format json
Fail CI when full verification is missing:
trustcheck inspect sampleproject --version 4.0.0 --strict
CLI reference
Primary command:
trustcheck inspect <project>
Supported flags:
--version: inspect a specific release instead of the latest project version--expected-repo: require repository evidence to match an expected GitHub or GitLab repository--format text|json: choose human-readable text or machine-readable JSON--verbose: include per-file provenance, digest, publisher, and note fields in text output--strict: return a failing exit code if every discovered artifact is not cryptographically verified--debug: print tracebacks for operational failures
Output model
The default text output is optimized for operators. It starts with a concise summary and then expands into evidence and risk details.
It includes:
- recommendation tier
- package URL and package summary
- verification coverage summary
- publisher trust depth
- "why this result" explanations
- declared repository URLs
- ownership and vulnerability data when PyPI exposes them
- per-risk remediation guidance
With --verbose, the report also shows per-file provenance, digest, attestation, publisher, and error details.
Recommendation tiers:
verified: every discovered release artifact verified successfullymetadata-only: no cryptographically verified artifact set, but no risk flags elevated the resultreview-required: medium-severity issues require manual reviewhigh-risk: high-severity issues were detected
Exit codes
trustcheck is designed to fit into automation as well as interactive review.
0: success1: upstream PyPI/network failure2: command usage error3: invalid or unexpected response / processing failure4: strict policy failure triggered by--strict
--strict is intentionally conservative:
- if no release files are discovered, it fails
- if any discovered file is not fully verified, it fails
JSON contract
trustcheck inspect --format json is the stable machine-readable interface.
Top-level shape:
{
"schema_version": "1",
"report": {
"project": "demo",
"version": "1.2.3",
"summary": "Demo package",
"package_url": "https://pypi.org/project/demo/1.2.3/",
"declared_repository_urls": ["https://github.com/example/demo"],
"repository_urls": ["https://github.com/example/demo"],
"expected_repository": "https://github.com/example/demo",
"ownership": {
"organization": "example-org",
"roles": []
},
"vulnerabilities": [],
"files": [],
"coverage": {
"total_files": 0,
"files_with_provenance": 0,
"verified_files": 0,
"status": "none"
},
"publisher_trust": {
"depth_score": 0,
"depth_label": "none",
"verified_publishers": [],
"unique_verified_repositories": [],
"unique_verified_workflows": []
},
"provenance_consistency": {
"has_sdist": false,
"has_wheel": false,
"sdist_wheel_consistent": null,
"consistent_repositories": [],
"consistent_workflows": []
},
"release_drift": {
"compared_to_version": null,
"publisher_repository_drift": null,
"publisher_workflow_drift": null,
"previous_repositories": [],
"previous_workflows": []
},
"risk_flags": [],
"recommendation": "verified"
}
}
Contract rules:
schema_versionversion-controls the JSON shape- patch releases keep the same JSON contract for a given schema version
- new fields may be added within
reportin a backward-compatible way - breaking JSON changes require a new
schema_version - text output is presentation-oriented and is not a compatibility contract
Repository matching rules
Repository matching is intentionally strict.
trustcheck currently normalizes and matches canonical repository roots for supported forges:
- GitHub
- GitLab
It accepts canonical repository URLs and equivalent git-style remotes, and rejects non-repository pages such as profile, organization, documentation, or archive URLs. Invalid --expected-repo values are reported explicitly as a risk condition rather than being matched loosely.
Trust and verification model
trustcheck does not treat project metadata alone as proof of origin.
The strongest result comes from verified provenance bound to the exact artifact digest that was downloaded. Repository URLs and publisher identity hints are useful context, but they are not equivalent to a cryptographically verified attestation.
That distinction is reflected in the report:
- metadata can support an explanation
- verified provenance can support a trust decision
- missing or unverifiable provenance drives risk flags and strict-policy failures
Common automation patterns
Fail a build if a pinned release is not fully verified:
trustcheck inspect sampleproject --version 4.0.0 --strict
Record JSON as a CI artifact:
trustcheck inspect sampleproject --version 4.0.0 --format json > trustcheck-report.json
Review a release against an expected repository during package admission:
trustcheck inspect sampleproject \
--version 4.0.0 \
--expected-repo https://github.com/pypa/sampleproject \
--strict
Quality and release process
The repository includes:
- CI for tests, lint, type checks, and build smoke tests
- release publishing from immutable tagged commits
- annotated tag enforcement for releases
- GitHub Release creation with generated notes
- release artifact checksum generation
- opt-in live integration tests against real PyPI packages
Live integration tests are excluded from the default test run and can be enabled with:
TRUSTCHECK_RUN_LIVE=1 python -m pytest -q tests/test_integration_live.py
Limitations
- PyPI metadata quality varies by project
- some projects do not publish provenance at all
- repository matching currently supports canonical GitHub and GitLab URLs only
- provenance verification may depend on local environment support required by underlying tooling
- text output is intentionally concise and may omit low-level detail unless
--verboseis used
Development
Run the local test suite:
python -m pytest -q tests
Run lint:
ruff check src tests
Run type checks:
mypy src
License
Project details
Release history Release notifications | RSS feed
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 trustcheck-1.2.0.tar.gz.
File metadata
- Download URL: trustcheck-1.2.0.tar.gz
- Upload date:
- Size: 31.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
ccc15c61ba0c9e719a053c2df1db43ba0bcd6356d1a01867ecc196253aaaf1fc
|
|
| MD5 |
bb722f647a9297d555fc7831ad868cdd
|
|
| BLAKE2b-256 |
3167b96505e10abfbf16c00d87360331f8f8d9377748572b921df3f37d589db4
|
Provenance
The following attestation bundles were made for trustcheck-1.2.0.tar.gz:
Publisher:
publish.yml on Halfblood-Prince/trustcheck
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
trustcheck-1.2.0.tar.gz -
Subject digest:
ccc15c61ba0c9e719a053c2df1db43ba0bcd6356d1a01867ecc196253aaaf1fc - Sigstore transparency entry: 1247178082
- Sigstore integration time:
-
Permalink:
Halfblood-Prince/trustcheck@2aa77db0a4a5435621e4ebbf39a1002eb36acbdb -
Branch / Tag:
refs/tags/v1.2.0 - Owner: https://github.com/Halfblood-Prince
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@2aa77db0a4a5435621e4ebbf39a1002eb36acbdb -
Trigger Event:
push
-
Statement type:
File details
Details for the file trustcheck-1.2.0-py3-none-any.whl.
File metadata
- Download URL: trustcheck-1.2.0-py3-none-any.whl
- Upload date:
- Size: 21.8 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
900013c56f248ee457d45918b55ac7696abb6539b05a0e1c87ba725eff59c76f
|
|
| MD5 |
8ab0970d4cc27c4ca54806d0aab5d210
|
|
| BLAKE2b-256 |
594ef8320bb60bd9d76a5d4a24eb110be7972dce0239d72e5c600a64682b89ff
|
Provenance
The following attestation bundles were made for trustcheck-1.2.0-py3-none-any.whl:
Publisher:
publish.yml on Halfblood-Prince/trustcheck
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
trustcheck-1.2.0-py3-none-any.whl -
Subject digest:
900013c56f248ee457d45918b55ac7696abb6539b05a0e1c87ba725eff59c76f - Sigstore transparency entry: 1247178089
- Sigstore integration time:
-
Permalink:
Halfblood-Prince/trustcheck@2aa77db0a4a5435621e4ebbf39a1002eb36acbdb -
Branch / Tag:
refs/tags/v1.2.0 - Owner: https://github.com/Halfblood-Prince
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@2aa77db0a4a5435621e4ebbf39a1002eb36acbdb -
Trigger Event:
push
-
Statement type: