Python API¶
trustcheck exposes a small supported public API for programmatic use.
Supported symbols¶
trustcheck.inspect_packagetrustcheck.PipResolvertrustcheck.TargetEnvironmenttrustcheck.Resolutiontrustcheck.ResolvedDistributiontrustcheck.ResolutionErrortrustcheck.discover_installed_distributionstrustcheck.TrustReporttrustcheck.TrustReport.to_dict()trustcheck.JSON_SCHEMA_VERSIONtrustcheck.JSON_SCHEMA_IDtrustcheck.get_json_schema()trustcheck.ExportPackagetrustcheck.SourceLocationtrustcheck.render_exporttrustcheck.package_purltrustcheck.OUTPUT_FORMATStrustcheck.INDUSTRY_OUTPUT_FORMATStrustcheck.OsvClienttrustcheck.OsvProvidertrustcheck.CisaKevClienttrustcheck.EpssClienttrustcheck.VulnerabilityIntelligenceClienttrustcheck.VulnerabilitySuppressiontrustcheck.HeuristicFindingtrustcheck.MaliciousPackageAssessmenttrustcheck.NativeBinaryInspectiontrustcheck.DEFAULT_TRUSTED_PROJECTStrustcheck.analyze_python_sourcetrustcheck.inspect_native_binarytrustcheck.heuristic_scoretrustcheck.ContentAddressedCachetrustcheck.AdvisorySnapshotStoretrustcheck.ADVISORY_SNAPSHOT_SCHEMAtrustcheck.PluginManagertrustcheck.PluginDescriptortrustcheck.PluginErrortrustcheck.AdvisorySourcePlugintrustcheck.IndexPlugintrustcheck.ArtifactAnalyzerPlugintrustcheck.PolicyRulePlugintrustcheck.RendererPlugintrustcheck.PLUGIN_API_VERSIONtrustcheck.PLUGIN_GROUPS
Everything else under trustcheck.* should be treated as internal implementation detail and may change between minor releases.
Vulnerability intelligence¶
from trustcheck import (
CisaKevClient,
EpssClient,
OsvClient,
OsvProvider,
VulnerabilityIntelligenceClient,
inspect_package,
)
intelligence = VulnerabilityIntelligenceClient(
providers=(
OsvProvider("OSV", OsvClient()),
OsvProvider(
"Private OSV",
OsvClient(base_url="https://advisories.example.com"),
),
),
kev_client=CisaKevClient(),
epss_client=EpssClient(),
)
report = inspect_package(
"jinja2",
version="2.10.0",
vulnerability_client=intelligence,
)
Configured providers are queried concurrently. Results merge by identifiers and aliases, then receive normalized CVSS, CWE, withdrawal, fix-version, KEV, and EPSS fields.
VulnerabilityIntelligenceClient.prefetch() performs bounded multi-package
OSV batch queries. An AdvisorySnapshotStore can be supplied for reusable
offline records, and flush_snapshots() atomically writes configured output.
Snapshot schema 2 includes source URLs, generation and expiration timestamps,
and a canonical record digest. Configure max_age, sigstore_identity, and
optionally sigstore_issuer when loading. Set sign_output=True when writing
with ambient Sigstore identity; unsigned compatibility requires the explicit
allow_unsigned=True setting.
Plugin API¶
PluginManager discovers entry points only when explicitly enabled. It routes
advisory sources, index clients, artifact analyzers, policy rules, and
renderers through the public protocol types listed above. Plugin API version
1 requires deterministic return values, thread-safe plugin instances, and
declared Trustcheck model or primitive result types. When the resource-bounded
worker is enabled, plugin IPC is versioned JSON bytes; the parent reconstructs
trusted models and rejects unknown fields or arbitrary custom result objects.
Trusted plugin loading also requires a signed statement bound to the installed
distribution version, RECORD digest, canonical installed-content digest,
dependencies, capabilities, configuration schema hash, and an external trust
root: either a trusted key fingerprint or an installed-content digest allowlist.
The runtime API remains version 1; signed plugin manifests and statements use
format version 2.
See Performance and extensibility for entry point group names and registration examples.
Industry exports¶
from trustcheck import (
ExportPackage,
SourceLocation,
inspect_package,
render_export,
)
report = inspect_package("sampleproject", version="4.0.0")
sarif = render_export(
"sarif",
[
ExportPackage(
report=report,
source=SourceLocation("requirements.txt", 12),
)
],
source_name="requirements.txt",
)
render_export accepts sarif, cyclonedx-json, cyclonedx-xml,
cyclonedx-1.7-json, cyclonedx-1.7-xml, spdx-json, spdx-3-json,
openvex, or markdown. ExportPackage.artifacts can carry lockfile
ArtifactReference records so multi-algorithm hashes are retained.
Malicious-package heuristics¶
from trustcheck import inspect_package
report = inspect_package(
"internal-sdkk",
inspect_artifacts=True,
trusted_projects=("internal-sdk",),
dependency_confusion_indexes=(
"https://pypi.org/simple",
"https://packages.example/simple",
),
)
print(report.malicious_package.score)
for finding in report.malicious_package.findings:
print(finding.code, finding.confidence, finding.location)
Metadata, name, index, ownership, repository, and cadence checks run without
artifact inspection. inspect_artifacts=True additionally parses bounded
Python source with ast and inspects PE, ELF, and Mach-O structure. Findings
are heuristic review indicators, not proof that a package is malicious.
Dependency resolution¶
Use PipResolver to obtain the exact package set selected by pip without
installing it:
from trustcheck import PipResolver, TargetEnvironment
resolution = PipResolver(sandbox_mode="auto").resolve_requirements_file(
"requirements.txt",
constraints=["constraints.txt"],
target=TargetEnvironment(
python_version="3.12",
platforms=("manylinux_2_28_x86_64",),
implementation="cp",
abis=("cp312",),
),
)
print(resolution.versions)
The resolver invokes pip with --dry-run --ignore-installed --report -.
It starts pip through the supported subprocess CLI, python -m pip, using the
configured python_executable; it does not import unsupported pip._internal
modules.
Cross-target resolution adds --only-binary :all: because source builds cannot
be performed correctly for a foreign target. sandbox_mode accepts off,
warn, auto, container, bubblewrap, and strict; the default is auto.
The selected mode and any fallback warnings are available
as resolution.sandbox_mode and resolution.sandbox_warnings.
container discovers Docker or Podman. bubblewrap requires Linux and
bwrap. auto prefers Bubblewrap, then a container, then strict wheel-only
resolution. Strict mode rejects requirement forms that can directly execute
source metadata hooks, tells pip to use isolated configuration and wheels
only, and loads a temporary sitecustomize.py audit guard through a minimal
PYTHONPATH so transitive backend or VCS commands fail closed. Container and
Bubblewrap execution stages only resolver inputs and referenced local
dependencies instead of mounting the project workspace. container_image
overrides the built-in image and must contain a full @sha256: digest.
Installed distributions¶
from trustcheck import discover_installed_distributions
active = discover_installed_distributions()
other = discover_installed_distributions(
[".venv/lib/python3.12/site-packages"]
)
Discovery uses importlib.metadata and reads PEP 610 direct_url.json when it
is available.
Example¶
from trustcheck import JSON_SCHEMA_VERSION, TrustReport, get_json_schema, inspect_package
report = inspect_package("sampleproject", version="4.0.0", include_dependencies=True)
payload = report.to_dict()
assert payload["schema_version"] == JSON_SCHEMA_VERSION
schema = get_json_schema()
assert schema["$id"]
Common patterns¶
Inspect a package inside a Python program¶
from trustcheck import inspect_package
report = inspect_package("sampleproject", version="4.0.0")
print(report.recommendation)
print(report.coverage.status)
Inspect direct dependencies too¶
from trustcheck import inspect_package
report = inspect_package(
"sampleproject",
version="4.0.0",
include_dependencies=True,
)
print(report.dependency_summary.total_inspected)
print(report.dependency_summary.highest_risk_recommendation)
for dependency in report.dependencies:
print(dependency.project, dependency.version, dependency.recommendation)
Inspect the full dependency tree¶
from trustcheck import inspect_package
report = inspect_package(
"sampleproject",
version="4.0.0",
include_transitive_dependencies=True,
)
print(report.dependency_summary.max_depth)
for dependency in report.dependencies:
print(dependency.project, dependency.depth)
Require a repository match before continuing¶
from trustcheck import inspect_package
report = inspect_package(
"sampleproject",
version="4.0.0",
expected_repository="https://github.com/pypa/sampleproject",
)
if report.recommendation in {"review-required", "high-risk"}:
raise SystemExit("package trust review required")
Convert the result to JSON-ready data¶
import json
from trustcheck import inspect_package
report = inspect_package("sampleproject", version="4.0.0", include_dependencies=True)
payload = report.to_dict()
print(json.dumps(payload, indent=2))
inspect_package¶
Use inspect_package(project, version=None, expected_repository=None, client=None,
progress_callback=None, include_dependencies=False,
include_transitive_dependencies=False, include_osv=False,
inspect_artifacts=False, dynamic_analysis=False, dynamic_analysis_image=None,
dynamic_analysis_python="3.12", osv_client=None, vulnerability_client=None,
locked_versions=None, resolver=None, target_environment=None,
complete_locked_versions=False, expected_artifacts=()) to collect evidence and
build a TrustReport.
In most applications, you only need to provide:
project- optionally
version - optionally
expected_repository - optionally
include_dependencies=Truewhen you want direct dependency inspection - optionally
include_transitive_dependencies=Truewhen you want recursive dependency inspection - optionally
include_osv=Trueto query OSV for the exact selected versions - optionally
vulnerability_client=VulnerabilityIntelligenceClient(...)to merge multiple advisory and enrichment providers - optionally
inspect_artifacts=Trueto statically inspect downloaded wheels and sdists - optionally
dynamic_analysis=Trueto run bounded install analysis in a digest-pinned analyzer image; setdynamic_analysis_python="3.13"for a configured profile ordynamic_analysis_image="image@sha256:..."for an explicit analyzer image. Profiles without a recorded digest-pinned analyzer image fail as unsupported rather than falling back to a generic Python image. - optionally
trusted_projects=("internal-sdk",)to extend the typosquatting reference set - optionally
dependency_confusion_indexes=(...)to attach a resolver-observed cross-index collision to the package assessment - optionally
locked_versions={"dependency-name": "1.2.3"}to retain resolved direct and transitive versions - optionally
target_environment=TargetEnvironment(...)for resolver target controls - optionally
expected_artifacts=(ArtifactReference(...),)to require locked filenames, URLs, sizes, and hashes
When dependency inspection is requested without locked_versions,
inspect_package resolves the root package and dependency set through
PipResolver.
PipResolver(indexes=IndexConfiguration(...)) supports primary and extra
PEP 503/691 indexes, keyring provider selection, source attribution, and
dependency-confusion detection. Cross-index collisions raise
ResolutionError unless allow_dependency_confusion=True. Dependency-confusion
findings expose an evidence tuple with resolver terminology, available
versions per index, and hash or metadata mismatches when the configured index
client can observe them.
load_lockfile(path, extras=(), groups=(), environment=None) returns a
LockfileResolution containing exact LockedPackage entries and retained
ArtifactReference records for PEP 751, Pipfile, uv, Poetry, and PDM locks.
SimpleRepositoryClient is the public PEP 503/691 parser and authenticated
index client.
Artifact inspection reads archive contents only. It does not import or execute the inspected package. Native signature fields report embedded signature presence, not cryptographic validity.
Progress callback example¶
When you want to surface progress in a script or UI, pass a callback that receives (filename, index, total):
from trustcheck import inspect_package
def on_progress(filename: str, index: int, total: int) -> None:
print(f"[{index}/{total}] verifying {filename}")
report = inspect_package(
"sampleproject",
version="4.0.0",
progress_callback=on_progress,
)
TrustReport¶
TrustReport is the main result object. It includes:
- package identity and summary
- declared dependency metadata
- repository signals
- vulnerabilities
- per-file provenance data
- coverage summary
- publisher trust summary
- provenance consistency
- release drift
- dependency inspection results and aggregate dependency summary
- policy evaluation
- diagnostics
- remediation summary
Use report.to_dict() when you need the stable JSON envelope.
Accessing report fields¶
from trustcheck import inspect_package
report = inspect_package("sampleproject", version="4.0.0")
for flag in report.risk_flags:
print(flag.severity, flag.code, flag.message)
for file in report.files:
print(file.filename, file.verified, file.error)
for provenance in file.slsa_provenance:
print(
provenance.source_repository,
provenance.source_commit,
provenance.builder_id,
)
for dependency in report.dependencies:
print(dependency.project, dependency.depth, dependency.recommendation, dependency.error)
The public deep-provenance surface includes SlsaProvenance,
ProvenanceMaterial, ProvenanceIssue, analyze_slsa_provenance(...), and
publisher-organization allowlist helpers. Normal package inspection populates
these models only after the SLSA statement, signature, subject filename, and
artifact digest have verified.
Remediation API¶
The public remediation surface includes:
plan_remediation(...)prepare_remediation(...)apply_prepared_remediation(...)create_pull_request(...)RemediationPlan,RemediationUpgrade,BlockedFix,FilePatch,SemanticEdit,RemediationValidation, andPullRequestResultREMEDIATION_SCHEMA_VERSIONandREMEDIATION_SCHEMA_ID
plan_remediation accepts a baseline Resolution, exact-version reports,
root requirements, and resolver/scanner callbacks. This keeps network and
policy configuration under application control. Only plans with status
validated can be passed to prepare_remediation; prepared changes expose
exact file bytes and patches and support context-manager cleanup.
Most callers should use the CLI because it supplies the same index, target matrix, advisory providers, and policy to every resolution and rescan.