Skip to main content

Package trust and provenance verification for PyPI consumers.

Project description

trustcheck Awesome

CI Source Build CodeQL pip-audit Bandit Semgrep Windows Defender ClamAV Ruff mypy Coverage PyPI Python 3.11 | 3.12 | 3.13 | 3.14 PyPI Downloads TrustCheck Package Scanner

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, and uv.lock, poetry.lock, or pdm.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-packages directories
  • 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/

Project support:

License

Trustcheck Personal Use License

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

trustcheck-2.0.5.tar.gz (1.0 MB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

trustcheck-2.0.5-py3-none-any.whl (167.8 kB view details)

Uploaded Python 3

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

Hashes for trustcheck-2.0.5.tar.gz
Algorithm Hash digest
SHA256 b7ca0f813b4c5375eb1280df51bd650b9bfdeb0b23be105d223fff660eff9236
MD5 d724031c9b2a7e87723b286b64a7e95c
BLAKE2b-256 6c822f279036f3552d63d79fc3ae99552592aacdfd63a62461260ae60050a147

See more details on using hashes here.

Provenance

The following attestation bundles were made for trustcheck-2.0.5.tar.gz:

Publisher: publish.yml on Halfblood-Prince/trustcheck

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

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

Hashes for trustcheck-2.0.5-py3-none-any.whl
Algorithm Hash digest
SHA256 32aa115de8fb80edd1fa4c20ecc84d2abd1b4acff3fe3281f340853a693f763b
MD5 0e06e97b2ccf0c0f055aa8ee6f18f3c4
BLAKE2b-256 5df0bf940ed3c74544e1c8edee4b329256724c46336da9692e82a2de1d2c3b0b

See more details on using hashes here.

Provenance

The following attestation bundles were made for trustcheck-2.0.5-py3-none-any.whl:

Publisher: publish.yml on Halfblood-Prince/trustcheck

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page