trustcheck [](https://awesome.re)
July 5, 2026 ยท View on GitHub
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.
Choose your workflow
| Command | Use it to |
|---|---|
scan | audit a project |
inspect | assess one package release |
install | verify before installing |
diff | review a dependency PR |
manifest | lock approved trust evidence |
impact | prioritize by observed usage |
Latest benchmark
Generated 2026-07-04T12:38:12.871592+00:00 on Python 3.14.6 with pip-audit 2.10.1. Corpus 2026.06 contains 133 entries; this fixed-input --no-deps comparison covers 112 comparable package entries.
| Tool | Cold p50 | Warm p50 | Warm p95 | Peak RSS | Requests p50 | Recall |
|---|---|---|---|---|---|---|
| trustcheck scan --fast | 16.00 s | 14.20 s | 14.44 s | 78.0 MiB | unknown | 1 |
| pip-audit | 36.69 s | 38.51 s | 39.82 s | 75.6 MiB | unknown | 1 |
Alias-aware agreement: 1.0 across 105 compared packages and 263 matched advisories.
Resolver exact match: True (trustcheck 22, pip-audit 22).
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
- verify source/release parity so declared repositories, release tags, artifacts, and attestations agree on one source commit
- 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
- verify and install dependencies in one gate with a temporary local wheelhouse and reproducible lock, report, and attestation evidence
- prioritize vulnerable packages by observed first-party imports, dependency reachability, test-only usage, development-only usage, and unresolved dynamic imports
- plan, dry-run, apply, or publish the smallest validated secure dependency upgrade set without silently widening declared constraints
- review dependency update pull requests by comparing only changed lockfile packages, trust metadata, artifacts, index origins, licenses, and manifest expectations
- 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 or 1.7 JSON/XML, SPDX 2.3 or SPDX 3 JSON, OpenVEX 0.2.0, or Markdown
- emit a concise decision report for release gates and pull request checks
Check local prerequisites before relying on resolver isolation, private indexes, or provenance verification:
trustcheck doctor
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]"
Project defaults can live in .trustcheck.toml or under [tool.trustcheck] in
pyproject.toml. CLI flags override environment variables, which override
project configuration. See the configuration guide.
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.11.0. Package and report
schema versions are independent so documentation-only package releases do not
force contract churn.
Pre-commit and monorepos
Trustcheck publishes a first-party hook for changed dependency files:
repos:
- repo: https://github.com/Halfblood-Prince/trustcheck
rev: v2
hooks:
- id: trustcheck
The hook runs --fast --no-deps --with-osv, preserves lockfile artifact hashes,
deduplicates filenames, and merges failures across every changed dependency file.
For monorepos, trustcheck-workspace . --format sarif discovers supported files,
aggregates repository-relative results, and accepts --baseline plus
--policy-overrides for per-project policies.
Use a trust manifest to approve the current dependency identities and block future trust regressions even when an upgrade is vulnerability-free:
trustcheck manifest init -f requirements.lock --output trustcheck.manifest.json
trustcheck manifest verify -f requirements.lock --manifest trustcheck.manifest.json
trustcheck manifest update -f requirements.lock --manifest trustcheck.manifest.json
The manifest records source repository and owner, verified Trusted Publisher identity and workflow, SLSA builder and build type, provenance and attestation coverage, package index origin, malicious-package score ceiling, native-binary allowance, dynamic-execution allowance, and expiring package exceptions.
Review dependency update pull requests with a trust diff that inspects only packages whose resolved version or source changed:
trustcheck diff requirements-old.lock requirements-new.lock
trustcheck diff --base origin/main --head HEAD --github-pr --format markdown
trustcheck diff --base origin/main --head HEAD --github-pr --comment
The diff highlights new direct and transitive packages, vulnerability and
malicious-package signals, provenance loss, repository or Trusted Publisher
changes, wheel or sdist native-binary changes, license and private-index origin
changes, and trust-manifest violations when --manifest is provided. Use
--format sarif to upload findings to code scanning.
TrustCheck Package Scanner
Use the TrustCheck Package Scanner action to scan a checked-in dependency file before merge:
steps:
- uses: actions/checkout@v7
- uses: Halfblood-Prince/trustcheck@v2
with:
target: requirements.txt
policy: strict
For a protected release gate, pin both actions to commit SHAs. GitHub treats a full commit SHA as the only immutable Action reference:
steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
- uses: Halfblood-Prince/trustcheck@<full-release-commit-sha>
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@v2
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 scan sampleproject --version 4.0.0 --fast
Scan profiles make the analysis depth explicit. --fast (the default) performs
dependency resolution and advisory lookup only. --standard adds provenance,
while --full adds static archives, native binaries, release history, and
malicious-package heuristics. Artifact breadth defaults to the best compatible
wheel for the requested target, with an sdist fallback.
trustcheck scan -f requirements.txt --standard
trustcheck scan sampleproject --version 4.0.0 --full --workers 8
trustcheck scan sampleproject --full --artifact-scope all --strict
Use --artifact-scope sdist for source review or --artifact-scope all for a
strict whole-release review. Release and promotion policies should scan every
published artifact, including wheels for other operating systems and
architectures:
trustcheck scan -f requirements.lock --full --artifact-scope all --strict
Verify and install the exact resolved dependency graph in one workflow:
trustcheck install -r requirements.txt --policy strict
trustcheck install -r requirements.txt --lock trustcheck.lock
trustcheck install requests==2.32.5 --require-provenance
trustcheck install resolves the complete graph, verifies the selected
artifacts, materializes a temporary verified wheelhouse, and invokes pip with
--no-index --find-links plus hash-pinned exact requirements. Nothing is
installed if policy, provenance, advisory, hash, artifact, or private-index
origin checks fail. Each run writes trustcheck.lock,
trustcheck-install-report.json, and trustcheck-install-attestation.json.
Prioritize vulnerable packages by observed application usage:
trustcheck impact -f requirements.lock --source .
trustcheck impact -f requirements.lock --source src --source services/api --format json
trustcheck impact combines the resolved dependency graph with a conservative
static import graph from first-party source, console-script metadata, pytest
plugins, and common framework imports. Findings are classified as directly
used, transitively reachable, test-only, development-only, not observed in
project source, or unknown due to dynamic loading. It never claims a dependency
is not exploitable; no first-party usage means only that static analysis did
not observe it, and dynamic imports, plugins, and runtime configuration still
require manual review.
Enrich vulnerability intelligence with OSV and GitHub Advisory Database data:
trustcheck scan jinja2 --version 2.10.0 --with-osv
Merge OSV, Ecosyste.ms, a private OSV-compatible service, CISA KEV, and FIRST EPSS intelligence:
trustcheck scan jinja2 \
--version 2.10.0 \
--with-osv \
--with-ecosystems \
--osv-url https://advisories.example.com \
--with-kev \
--with-epss
Gate only critical, known-exploited, or fixable vulnerabilities:
trustcheck scan -f 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 inspect -f requirements.txt
Resolution uses pip install --dry-run --report and includes transitive
packages selected by pip:
trustcheck scan -f requirements.txt \
--constraint constraints.txt \
--python-version 3.12 \
--platform manylinux_2_28_x86_64 \
--implementation cp \
--abi cp312
Pip may invoke build-backend metadata hooks even in dry-run mode. Trustcheck can isolate that resolver invocation:
trustcheck scan -f requirements.txt --sandbox auto
--sandbox auto is the default. It prefers Bubblewrap on Linux, then Docker or
Podman, and falls back to strict wheel-only resolution when no runtime is
available. The full mode set is:
warn: explicitly preserve host pip behavior and emit an execution-risk warningoff: preserve pip behavior without the warningcontainer: run pip as an unprivileged process in a read-only Docker/Podman container with dropped capabilities and only staged resolver inputs mountedbubblewrap: run pip in low-privilege Linux namespaces with a read-only staged input tree, read-only system paths, and a cleared environmentstrict: reject editable, VCS, local non-wheel, direct non-wheel, and source archive inputs, ignore user pip configuration, and require wheels for every resolved package; child-process creation is denied so unexpected transitive source hooks and VCS commands fail closed
Container and Bubblewrap modes retain network access for package-index
resolution. Requirements, nested includes, constraints, dependency-group
files, and referenced local dependencies are copied to a temporary input tree;
the project workspace is not mounted. Container images must be pinned by a
full SHA-256 digest when supplied with --sandbox-image. Cross-target
resolution is always wheel-only.
Inspect dependencies declared in a TOML project file:
trustcheck inspect -f pyproject.toml
Plan the smallest constraint-compatible secure upgrade set:
trustcheck scan -f requirements.txt \
--with-osv \
--plan-fixes \
--remediation-output reports/trustcheck-remediation.json
Generate and validate the exact patch without changing dependency files:
trustcheck scan -f pyproject.toml --with-osv --fix --dry-run
Apply the same transaction only after re-resolution, a clean virtualenv
install, pip check, configured validation commands, and a complete rescan:
trustcheck scan -f uv.lock --with-osv --fix
Configured fix validation commands live under [tool.trustcheck.fix]:
[tool.trustcheck.fix]
test_commands = ["pytest -q", "python -m compileall src"]
Successful fix runs write a review patch such as trustcheck-fix.patch and
record the exact path in the remediation output.
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 -f pyproject.toml --extra security --group test
Inspect exact direct and transitive versions from a supported lockfile:
trustcheck inspect -f pylock.toml --with-transitive-deps
trustcheck scan -f Pipfile.lock
Run a bounded, resumable scan and publish an advisory snapshot:
trustcheck scan -f requirements.txt \
--with-osv \
--workers 8 \
--resume-state .trustcheck/scan-state.json \
--write-advisory-snapshot .trustcheck/advisories.json \
--sign-advisory-snapshot
Signed snapshots include source URLs, generation and expiration times, and a
SHA-256 digest of canonical advisory records. Reading one requires the trusted
Sigstore certificate identity and accepts snapshots for at most seven days by
default; adjust that bound with --max-advisory-age HOURS.
Enable an installed, signed plugin explicitly:
trustcheck scan -f requirements.txt --plugin policy:company-policy
Every plugin must be explicitly allowlisted. Trustcheck verifies its signed
trustcheck-plugin.json name, kind, entry point, and API version before using a
spawned resource-bounded worker. Optional signer fingerprints live under
_trustcheck.trusted_signers in plugin config. Each call is reported in
diagnostics.plugin_executions with status, duration, and isolation state.
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 -f requirements.txt \
--index-url https://username@packages.example.com/simple \
--keyring-provider subprocess
Adding a public fallback is deliberately guarded:
trustcheck scan -f 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.
For behavior evidence, --dynamic-analysis is available as an explicit opt-in.
It executes downloaded artifacts in a disposable Docker container with no
network, a non-root user, dropped capabilities, and strict CPU, memory, process,
and wall-clock limits. The dynamic-analysis image is digest-pinned by default,
and mutable image tags are rejected. It is never enabled by default.
Name, index, ownership, repository, and release-cadence heuristics run during
normal inspection. Add organization-specific reference names with repeatable
--trusted-project:
trustcheck inspect -f requirements.txt \
--trusted-project internal-sdk \
--trusted-project internal-auth
Require a release to match an expected repository:
trustcheck inspect sampleproject \
--version 4.0.0 \
--expected-repo https://github.com/pypa/sampleproject
Require source/release provenance parity for a package release:
trustcheck inspect sampleproject \
--version 4.0.0 \
--source-release-provenance \
--release-tag v4.0.0
Emit JSON for another tool:
trustcheck inspect sampleproject --version 4.0.0 --format json
Emit only the gate decision fields:
trustcheck scan -f requirements.txt --summary
Emit combined JSON for a requirements-style, TOML, or lockfile scan:
trustcheck scan -f requirements.txt --format json
Write SARIF, SBOM, VEX, or Markdown output directly to a file:
trustcheck scan -f requirements.txt \
--format sarif \
--output-file reports/trustcheck.sarif
trustcheck scan -f pylock.toml \
--format cyclonedx-json \
--output-file reports/trustcheck.cdx.json
Supported industry formats are sarif, cyclonedx-json, cyclonedx-xml,
cyclonedx-1.7-json, cyclonedx-1.7-xml, spdx-json, spdx-3-json,
openvex, and markdown. The unversioned CycloneDX and SPDX format names
remain compatible aliases for CycloneDX 1.6 and SPDX 2.3. SBOM exports retain
package purls, vulnerabilities, provenance coverage, artifact hashes,
recommendations, and policy violations.
Emit only vulnerability records as JSON:
trustcheck scan sampleproject --version 4.0.0 --format json
Fail CI when full verification is missing:
trustcheck inspect sampleproject --version 4.0.0 --strict
Starter policy bundles include startup, regulated,
enterprise-private-index, release-gate, and open-source-maintainer:
trustcheck scan -f requirements.txt --policy release-gate
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
