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.
Packages that publish no provenance are treated as needing review rather than as automatic high-risk findings, while invalid provenance, partial coverage, repository mismatches, and known vulnerabilities remain stronger negative signals.
What it checks
For a selected package version, trustcheck can:
- fetch project and release metadata from PyPI
- verify published provenance against artifact digests
- interpret SLSA v1 build definitions, builders, source materials, commits, workflows, and resolved build dependencies
- detect mutable workflow references, unpinned build actions, and source-to-artifact inconsistencies
- surface Trusted Publisher repository and workflow identity hints
- compare signer, repository, workflow, builder, build type, and source commit evidence across release history
- compare expected repository input against declared and attested signals
- flag publisher drift, missing verification, and known vulnerabilities
- scan requirements files, project TOML,
pylock.toml,Pipfile.lock, pip-tools output, anduv.lock,poetry.lock, orpdm.lock - resolve complete dependency sets with pip installation reports, including constraints, nested requirements, extras, dependency groups, editable requirements, and VCS references
- audit the active Python environment or arbitrary
site-packagesdirectories - resolve against PEP 503/691 private indexes with optional keyring credentials
- block dependency-confusion collisions across public and private indexes
- preserve and verify lockfile artifact hashes before trusting downloaded bytes
- plan, dry-run, apply, or publish the smallest validated secure dependency upgrade set without silently widening declared constraints
- batch OSV queries, bound concurrent target work, and store responses by verified SHA-256 content digest
- consume offline advisory snapshots, resume interrupted scans, and load explicitly enabled advisory, index, artifact, policy, or renderer plugins
- optionally inspect wheel and sdist contents without importing or executing package code
- score typosquatting, dependency-confusion, package-history, source-code, and native-binary heuristic indicators without claiming a malware verdict
- emit text, JSON, SARIF 2.1.0, CycloneDX 1.6 JSON/XML, SPDX 2.3 JSON, OpenVEX 0.2.0, or Markdown
Every push also builds standalone Windows and Linux executables. The Windows
artifact is scanned with Microsoft Defender's MpCmdRun.exe; the Linux
artifact is scanned with ClamAV. Clean binaries, checksums, and scanner reports
are retained as workflow artifacts by
Binary Security.
Installation
Install from PyPI:
pip install trustcheck
Install the optional Python keyring provider when private-index credentials are stored in an in-process keyring backend:
pip install "trustcheck[keyring]"
Or install the Snap Store package:
sudo snap install trustcheck
The Snap command is trustcheck. If the shell reports command not found
immediately after installation, start a new login session or add Snap's
command directory to the current shell:
export PATH="/snap/bin:$PATH"
trustcheck --version
You can always bypass shell PATH lookup with:
snap run trustcheck inspect requests
PyPI installation requirements:
- Python
>=3.11 - Network access to PyPI
Machine-readable reports currently use JSON schema 1.9.0. Package and report
schema versions are independent so documentation-only package releases do not
force contract churn.
TrustCheck Package Scanner
Use the TrustCheck Package Scanner action to scan a checked-in dependency file before merge:
steps:
- uses: actions/checkout@v6
- uses: Halfblood-Prince/trustcheck@v1
with:
target: requirements.txt
policy: strict
The action installs and runs trustcheck, uploads trustcheck-report.json as
a workflow artifact, and fails the job with the CLI's exit code when policy
evaluation fails. target also accepts a PyPI package name, pyproject.toml,
pylock.toml, Pipfile.lock, uv.lock, poetry.lock, or pdm.lock.
Each stable release publishes an immutable full version tag and updates the
compatible major action tag used above.
Produce SARIF for GitHub code scanning without repeating the audit:
- uses: Halfblood-Prince/trustcheck@v1
id: trustcheck
with:
target: requirements.txt
format: sarif
- uses: github/codeql-action/upload-sarif@v4
if: always()
with:
sarif_file: ${{ steps.trustcheck.outputs.report-path }}
See the CI integration guide for custom policies, OSV, dependency traversal, outputs, and report naming.
Quick start
Inspect the latest release:
trustcheck inspect requests
Inspect a specific version:
trustcheck inspect sampleproject --version 4.0.0
Show only known vulnerabilities for a release:
trustcheck inspect sampleproject --version 4.0.0 --cve
Enrich vulnerability intelligence with OSV and GitHub Advisory Database data:
trustcheck inspect jinja2 --version 2.10.0 --with-osv --cve
Merge OSV, Ecosyste.ms, a private OSV-compatible service, CISA KEV, and FIRST EPSS intelligence:
trustcheck inspect jinja2 \
--version 2.10.0 \
--with-osv \
--with-ecosystems \
--osv-url https://advisories.example.com \
--with-kev \
--with-epss \
--cve
Gate only critical, known-exploited, or fixable vulnerabilities:
trustcheck scan pylock.toml --fail-on-vulnerability kev
Require verified publishers to belong to an approved organization:
trustcheck inspect sampleproject \
--version 4.0.0 \
--trusted-publisher-organization github:pypa
Custom policy files can suppress a specific advisory temporarily, but every suppression must name an owner, justification, and ISO expiration date.
Inspect a package and its direct dependencies:
trustcheck inspect sampleproject --version 4.0.0 --with-deps
Inspect the full transitive dependency tree:
trustcheck inspect sampleproject --version 4.0.0 --with-transitive-deps
Inspect every package listed in a requirements-style file:
trustcheck scan requirements.txt
Resolution uses pip install --dry-run --report and includes transitive
packages selected by pip:
trustcheck scan requirements.txt \
--constraint constraints.txt \
--python-version 3.12 \
--platform manylinux_2_28_x86_64 \
--implementation cp \
--abi cp312
Resolver note: pip may invoke build-backend metadata hooks for source, local, editable, or VCS requirements even in dry-run mode. Do not resolve an untrusted source requirement outside an appropriate sandbox. Cross-target resolution is wheel-only.
Inspect dependencies declared in a TOML project file:
trustcheck scan pyproject.toml
Plan the smallest constraint-compatible secure upgrade set:
trustcheck scan requirements.txt \
--with-osv \
--plan-fixes \
--remediation-output reports/trustcheck-remediation.json
Generate and validate the exact patch without changing the working tree:
trustcheck scan pyproject.toml --with-osv --fix --dry-run
Apply the same transaction only after re-resolution and a complete rescan:
trustcheck scan uv.lock --with-osv --fix
Secure versions excluded by a declared range remain blocked unless
--allow-constraint-changes is passed. Editable, local-path, direct-archive,
and VCS dependencies are reported as requiring human remediation.
Select project extras and dependency groups:
trustcheck scan pyproject.toml --extra security --group test
Inspect exact direct and transitive versions from a supported lockfile:
trustcheck scan pylock.toml --with-transitive-deps
trustcheck scan Pipfile.lock
Run a bounded, resumable scan and publish an advisory snapshot:
trustcheck scan requirements.txt \
--with-osv \
--max-workers 8 \
--resume-state .trustcheck/scan-state.json \
--write-advisory-snapshot .trustcheck/advisories.json
Enable an installed plugin explicitly:
trustcheck scan requirements.txt --plugin policy:company-policy
Hash-pinned pip-tools output is detected automatically. Every retained
lockfile hash is emitted in combined JSON and checked against the downloaded
artifact. This integrity check does not require --inspect-artifacts.
Resolve and audit from a private PEP 503/691 index:
trustcheck scan requirements.txt \
--index-url https://username@packages.example.com/simple \
--keyring-provider subprocess
Adding a public fallback is deliberately guarded:
trustcheck scan requirements.txt \
--index-url https://username@packages.example.com/simple \
--extra-index-url https://pypi.org/simple
If the same normalized project name exists on both indexes, the scan stops
with a dependency-confusion error. --allow-dependency-confusion is available
for a source collision that has been independently reviewed; the finding
remains in combined JSON.
Audit the active environment:
trustcheck environment
Audit one or more explicit site-packages directories:
trustcheck environment --path .venv/lib/python3.12/site-packages
Statically inspect wheel and sdist contents:
trustcheck inspect sampleproject --version 4.0.0 --inspect-artifacts --verbose
Artifact inspection validates wheel RECORD hashes, lists console scripts,
parses Python source with ast, detects suspicious capability combinations,
and compares wheel and sdist metadata. PE, ELF, and Mach-O files are inspected
for imported libraries, embedded signature presence, entropy, and embedded
payload signatures. It reads archive bytes only and never imports the
inspected package.
Name, index, ownership, repository, and release-cadence heuristics run during
normal inspection. Add organization-specific reference names with repeatable
--trusted-project:
trustcheck scan requirements.txt \
--trusted-project internal-sdk \
--trusted-project internal-auth
Every malicious-package finding is explicitly labeled as a heuristic indicator for review, not proof that a package is malicious.
Require a release to match an expected repository:
trustcheck inspect sampleproject \
--version 4.0.0 \
--expected-repo https://github.com/pypa/sampleproject
Emit JSON for another tool:
trustcheck inspect sampleproject --version 4.0.0 --format json
Emit combined JSON for a requirements-style, TOML, or lockfile scan:
trustcheck scan requirements.txt --format json
Write SARIF, SBOM, VEX, or Markdown output directly to a file:
trustcheck scan requirements.txt \
--format sarif \
--output-file reports/trustcheck.sarif
trustcheck scan pylock.toml \
--format cyclonedx-json \
--output-file reports/trustcheck.cdx.json
Supported industry formats are sarif, cyclonedx-json, cyclonedx-xml,
spdx-json, openvex, and markdown. SBOM exports retain package purls,
vulnerabilities, provenance coverage, artifact hashes, recommendations, and
policy violations.
Emit only vulnerability records as JSON:
trustcheck inspect sampleproject --version 4.0.0 --cve --format json
Fail CI when full verification is missing:
trustcheck inspect sampleproject --version 4.0.0 --strict
Use it from Python:
from trustcheck import inspect_package
report = inspect_package("sampleproject", version="4.0.0", include_dependencies=True)
print(report.recommendation)
Documentation
Full documentation: https://halfblood-prince.github.io/trustcheck/
- Getting started: Installation and Quickstart
- CLI usage: CLI overview, Policies, and Config and offline mode
- Integrations: JSON contract, Python API, and Compatibility
- Trust model: Verification model and repository matching
- Automation: CI integration
- Performance and extensibility: Batching, caching, snapshots, resume state, and plugins
- Benchmarks: Reproducible comparison with pip-audit
- Project details: Changelog
Project support:
- Bugs and feature requests: GitHub Issues
- Sensitive security reports: GitHub private vulnerability reporting
- Security policy: SECURITY.md
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-2.0.5.tar.gz.
File metadata
- Download URL: trustcheck-2.0.5.tar.gz
- Upload date:
- Size: 1.0 MB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b7ca0f813b4c5375eb1280df51bd650b9bfdeb0b23be105d223fff660eff9236
|
|
| MD5 |
d724031c9b2a7e87723b286b64a7e95c
|
|
| BLAKE2b-256 |
6c822f279036f3552d63d79fc3ae99552592aacdfd63a62461260ae60050a147
|
Provenance
The following attestation bundles were made for trustcheck-2.0.5.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-2.0.5.tar.gz -
Subject digest:
b7ca0f813b4c5375eb1280df51bd650b9bfdeb0b23be105d223fff660eff9236 - Sigstore transparency entry: 1815868317
- Sigstore integration time:
-
Permalink:
Halfblood-Prince/trustcheck@6872ebde429a49f989615517adcf1cc3bcf8dd72 -
Branch / Tag:
refs/tags/v2.0.5 - Owner: https://github.com/Halfblood-Prince
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@6872ebde429a49f989615517adcf1cc3bcf8dd72 -
Trigger Event:
push
-
Statement type:
File details
Details for the file trustcheck-2.0.5-py3-none-any.whl.
File metadata
- Download URL: trustcheck-2.0.5-py3-none-any.whl
- Upload date:
- Size: 167.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 |
32aa115de8fb80edd1fa4c20ecc84d2abd1b4acff3fe3281f340853a693f763b
|
|
| MD5 |
0e06e97b2ccf0c0f055aa8ee6f18f3c4
|
|
| BLAKE2b-256 |
5df0bf940ed3c74544e1c8edee4b329256724c46336da9692e82a2de1d2c3b0b
|
Provenance
The following attestation bundles were made for trustcheck-2.0.5-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-2.0.5-py3-none-any.whl -
Subject digest:
32aa115de8fb80edd1fa4c20ecc84d2abd1b4acff3fe3281f340853a693f763b - Sigstore transparency entry: 1815868946
- Sigstore integration time:
-
Permalink:
Halfblood-Prince/trustcheck@6872ebde429a49f989615517adcf1cc3bcf8dd72 -
Branch / Tag:
refs/tags/v2.0.5 - Owner: https://github.com/Halfblood-Prince
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@6872ebde429a49f989615517adcf1cc3bcf8dd72 -
Trigger Event:
push
-
Statement type: