Skip to content

Performance and extensibility

Bounded concurrency

--workers N bounds target scans, artifact downloads, provenance requests, static archive checks, advisory providers, OSV advisory fetches, and enrichment work. The default is 8; accepted values are 1 through 64, or -1 for all available CPU cores.

trustcheck scan -f requirements.txt --with-osv --workers 8

Results remain in resolved-input order even when workers finish out of order. Each target uses an isolated mutable PyPI client while sharing the persistent content store, digest-keyed artifact cache, advisory cache, and bounded HTTP connection pool. Concurrent requests for the same artifact digest are coalesced into one download.

Artifact and provenance work is predominantly network and archive I/O. CUDA or other GPU acceleration would add transfer and deployment overhead without speeding up these operations, so Trustcheck uses bounded CPU threads instead.

The same setting is available as TRUSTCHECK_MAX_WORKERS, performance.max_workers in the JSON config file, and the GitHub Action workers input.

Artifact scope

scan defaults to --artifact-scope target. Trustcheck ranks wheel tags for the requested Python, ABI, implementation, and platform, inspects the best compatible non-yanked wheel, and falls back to one sdist when no compatible wheel exists. This avoids downloading artifacts the target cannot install.

Use --artifact-scope sdist for source-only review. Use --full --artifact-scope all when reviewing every file published for a release.

OSV batch queries

Multi-package scans use OSV /v1/querybatch in chunks of at most 1,000 queries. Trustcheck follows each query's pagination token, deduplicates advisory IDs, and fetches every full advisory record once with bounded concurrency. OSV-compatible providers without the batch endpoint fall back to bounded individual queries.

Content-addressed cache

--cache-dir stores response bodies by SHA-256 under objects/sha256/<prefix>/<digest>. Request references live separately under refs/. Reads verify both the object size and SHA-256 digest; corrupted or missing objects fail closed with cache_integrity_failed.

This layout deduplicates identical responses and artifact bytes while keeping request lookup deterministic. Legacy request-addressed cache files remain readable during migration.

Advisory snapshots

Use a versioned snapshot to make advisory results portable and available to offline scans:

trustcheck scan -f requirements.txt \
  --with-osv \
  --write-advisory-snapshot .trustcheck/advisories.json \
  --sign-advisory-snapshot

trustcheck scan -f requirements.txt \
  --offline \
  --cache-dir .trustcheck/cache \
  --advisory-snapshot .trustcheck/advisories.json \
  --advisory-snapshot-identity \
    https://github.com/example/project/.github/workflows/snapshot.yml@refs/heads/main \
  --advisory-snapshot-issuer https://token.actions.githubusercontent.com \
  --max-advisory-age 24

--advisory-snapshot is repeatable. Inputs merge deterministically and deduplicate advisory identities. --write-advisory-snapshot writes the merged set atomically using schema urn:trustcheck:advisory-snapshot:2.0.0.

Schema 2 records a source manifest with provider URLs and a bound SHA-256 digest of canonical advisory records, plus generation and expiration timestamps. --sign-advisory-snapshot creates a Sigstore bundle beside the JSON as <snapshot>.sigstore.json using ambient OIDC identity. Loading verifies that bundle against --advisory-snapshot-identity and optional --advisory-snapshot-issuer before parsing records. --max-advisory-age HOURS defaults to 168 and can impose a shorter lifetime than the signed snapshot. Legacy or unsigned snapshots are accepted only with --allow-unsigned-advisory-snapshot.

The snapshot covers vulnerability intelligence. Offline package metadata and artifacts still require a populated content cache.

Resumable scans

scan and environment accept --resume-state PATH:

trustcheck scan -f requirements.txt \
  --with-osv \
  --resume-state .trustcheck/scan-state.json

Every completed target is checkpointed atomically. A restarted scan restores successful reports and retries failed targets. State is accepted only when its fingerprint matches the source digest, resolved targets, policy, indexes, advisory options, and enabled plugins. Stale or mismatched state fails closed.

Plugins

Plugins are disabled by default and require an explicit allowlist. Signed trustcheck-plugin.json manifests bind the name, kind, entry point, and API version. Trustcheck verifies the signature and optional signer-fingerprint allowlist before importing code in a spawned, resource-bounded worker. Execution status, timing, and isolation are included in report diagnostics.

trustcheck scan -f requirements.txt \
  --plugin advisory:company-osv \
  --plugin policy:company-policy \
  --plugin-config trustcheck-plugins.json

Supported entry-point groups:

Kind Entry-point group Purpose
Advisory trustcheck.advisory_sources Return normalized vulnerability records
Index trustcheck.indexes Route custom index schemes and repositories
Artifact trustcheck.artifact_analyzers Add heuristic artifact findings
Policy trustcheck.policy_rules Add enforced policy violations
Renderer trustcheck.renderers Add output formats

Example registration:

[project.entry-points."trustcheck.policy_rules"]
company-policy = "company_trustcheck:CompanyPolicy"

Plugin objects declare a stable name. Configuration is a JSON object keyed by that name. Plugin API version 1 uses the public protocols exported by trustcheck. The distribution includes trustcheck-plugin.json:

{
  "schema": "urn:trustcheck:plugin-manifest:1",
  "manifest": {
    "name": "company-policy",
    "kind": "policy",
    "entry_point": "company_trustcheck:CompanyPolicy",
    "api_version": "1"
  },
  "public_key": "-----BEGIN PUBLIC KEY-----...",
  "signature": "base64-rsa-pkcs1v15-sha256"
}

The signature covers canonical compact JSON for manifest with sorted keys. Exceptions, timeouts, signature failures, and contract violations fail closed.

The GitHub Action exposes enable-plugins, plugins, and plugin-config. The workflow must install plugin distributions before invoking the composite action.