Skip to content

JSON contract

trustcheck inspect --format json is the stable machine-readable interface for trust evidence. trustcheck scan --format json is the vulnerability-only interface for a single PyPI package.

Stability rules

  • schema_version is semantic and version-controls the JSON shape
  • JSON_SCHEMA_ID identifies the exact JSON Schema document for a given schema_version
  • patch releases keep the same JSON contract for a given schema version
  • new fields may be added within expandable objects in a backward-compatible way
  • breaking JSON changes require a new major schema_version

Current schema identifiers

  • JSON_SCHEMA_VERSION = "1.12.0"
  • JSON_SCHEMA_ID = "urn:trustcheck:report:1.12.0"

Package versions and report schema versions are independent. Schema 1.12.0 adds the expanded dynamic-analysis result contract, including phased execution status, sandbox mode metadata, failure classification, Python profile details, filesystem controls, and structured behavioral evidence.

Top-level shape

{
  "schema_version": "1.12.0",
  "report": {
    "project": "demo",
    "version": "1.2.3",
    "summary": "Demo package",
    "package_url": "https://pypi.org/project/demo/1.2.3/",
    "declared_dependencies": ["depalpha>=1.0"],
    "diagnostics": {
      "timeout": 10.0,
      "max_retries": 2,
      "backoff_factor": 0.25,
      "offline": false,
      "cache_dir": null,
      "request_count": 3,
      "retry_count": 1,
      "cache_hit_count": 0,
      "request_failures": [],
      "artifact_failures": []
    },
    "policy": {
      "profile": "default",
      "passed": true,
      "enforced": false,
      "fail_on_severity": "none",
      "require_verified_provenance": "none",
      "require_expected_repository_match": false,
      "allowed_publisher_organizations": [],
      "allow_metadata_only": true,
      "vulnerability_mode": "ignore",
      "suppressions_applied": 0,
      "suppressions_expired": 0,
      "violations": []
    },
    "declared_repository_urls": ["https://github.com/example/demo"],
    "repository_urls": ["https://github.com/example/demo"],
    "expected_repository": "https://github.com/example/demo",
    "ownership": {
      "organization": "example-org",
      "roles": []
    },
    "vulnerabilities": [
      {
        "id": "CVE-2026-1234",
        "summary": "Example vulnerability",
        "aliases": ["GHSA-abcd-1234-5678"],
        "source": "PyPI, OSV",
        "severity": "HIGH",
        "cvss_score": 8.8,
        "cvss_vector": "CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H",
        "cvss_version": "3.1",
        "cwes": ["CWE-79"],
        "fixed_in": ["1.2.4"],
        "link": "https://osv.dev/vulnerability/CVE-2026-1234",
        "withdrawn": false,
        "withdrawn_at": null,
        "kev": true,
        "kev_date_added": "2026-05-01",
        "kev_due_date": "2026-05-22",
        "kev_required_action": "Apply the vendor update.",
        "kev_known_ransomware_campaign_use": "Known",
        "epss_score": 0.8123,
        "epss_percentile": 0.9812,
        "epss_date": "2026-06-12",
        "suppression": null
      }
    ],
    "files": [],
    "coverage": {
      "total_files": 0,
      "files_with_provenance": 0,
      "verified_files": 0,
      "status": "none"
    },
    "publisher_trust": {
      "depth_score": 0,
      "depth_label": "none",
      "verified_publishers": [],
      "unique_verified_repositories": [],
      "unique_verified_workflows": []
    },
    "provenance_consistency": {
      "has_sdist": false,
      "has_wheel": false,
      "sdist_wheel_consistent": null,
      "consistent_repositories": [],
      "consistent_workflows": [],
      "builder_consistent": null,
      "source_commit_consistent": null,
      "build_type_consistent": null,
      "consistent_builders": [],
      "consistent_source_commits": [],
      "consistent_build_types": []
    },
    "release_drift": {
      "compared_to_version": null,
      "publisher_repository_drift": null,
      "publisher_workflow_drift": null,
      "signer_drift": null,
      "builder_drift": null,
      "source_commit_drift": null,
      "build_type_drift": null,
      "previous_signers": [],
      "previous_repositories": [],
      "previous_workflows": [],
      "previous_builders": [],
      "previous_source_commits": [],
      "previous_build_types": []
    },
    "malicious_package": {
      "score": 0,
      "level": "none",
      "artifact_analysis": false,
      "trusted_name_count": 56,
      "findings": [],
      "score_thresholds": {
        "low": 1,
        "elevated": 25,
        "high": 50,
        "critical": 75
      },
      "rule_thresholds": {},
      "disclaimer": "These findings are heuristic indicators for review, not proof that the package is malicious."
    },
    "dependencies": [
      {
        "requirement": "depalpha>=1.0",
        "project": "depalpha",
        "version": "1.4.0",
        "depth": 1,
        "parent_project": "demo",
        "parent_version": "1.2.3",
        "package_url": "https://pypi.org/project/depalpha/1.4.0/",
        "recommendation": "review-required",
        "risk_flags": [],
        "declared_dependencies": [],
        "error": null
      }
    ],
    "dependency_summary": {
      "requested": true,
      "total_declared": 1,
      "total_inspected": 1,
      "unique_dependencies": 1,
      "max_depth": 1,
      "highest_risk_recommendation": "review-required",
      "highest_risk_projects": ["depalpha"]
    },
    "risk_flags": [],
    "remediation": {
      "status": "not-requested",
      "minimal": false,
      "attempts": 0,
      "upgrades_planned": 0,
      "blocked_fixes": 0,
      "patch_files": [],
      "pull_request_url": null
    },
    "recommendation": "verified"
  }
}

Deep provenance fields

Each report.files[] item contains slsa_provenance. A verified SLSA v1 statement records:

  • signer identity derived from the verified Trusted Publisher
  • normalized source URI, repository, and full git commit
  • builder identity, build type, and invocation ID
  • workflow repository, path, reference, and whether the reference is immutable
  • resolved materials with names, URIs, digests, and source designation
  • discovered action references and the subset not pinned to full commits
  • structured provenance issues with code, severity, message, and evidence

report.provenance_consistency compares repository, workflow, builder, source commit, and build type between verified sdists and wheels. report.release_drift compares signer, repository, workflow, builder, source commit, and build type with the previous release. Source commit drift is recorded for auditability but is not by itself treated as suspicious because a new release normally comes from a new commit.

Dependency fields

When dependency inspection is enabled with --with-deps, --with-transitive-deps, include_dependencies=True, or include_transitive_dependencies=True, the report may include:

  • report.declared_dependencies: raw requires_dist strings from the inspected release metadata
  • report.dependencies: flattened dependency inspection results for the resolved dependency set
  • report.dependency_summary: aggregate counts and the highest-risk recommendation seen among inspected dependencies

If dependency inspection is not requested, these fields are still present in the contract with empty or default values so JSON consumers can rely on a stable shape.

File scan resolution metadata

trustcheck inspect -f <file> --format json, trustcheck scan -f <file> --format json, and trustcheck environment --format json include a top-level resolved array alongside reports and failures. Each entry records:

  • the exact resolved project and version
  • whether the distribution was explicitly requested
  • its direct source URL when pip or PEP 610 metadata provides one
  • editable status
  • VCS type and immutable commit identifier when available
  • the redacted source index URL
  • every retained lockfile artifact filename, URL, path, size, kind, and hash
  • configured-index collisions in dependency_confusion
  • the dependency manifest path and best-effort declaration line in source_file and source_line

For inspect -f and environment, each item in reports uses the full per-package report schema. For scan -f, each item is a minimal vulnerability object containing project, version, package_url, vulnerabilities, and an optional remediation summary when remediation was requested.

When remediation is requested, combined scan JSON also includes a top-level remediation object using urn:trustcheck:remediation:1.1.0. It contains before/after dependency graph digests and nodes, advisory IDs removed, source digests, semantic edits, unified diffs, lockfile hash validation records, post-fix reproduction commands and result digests, selected upgrades, blocked fixes, minimality status, validation results, and optional pull-request metadata. The same object can be written independently with --remediation-output.

Artifact URLs and index URLs never expose embedded credentials. Lock hashes are represented as an algorithm-to-hex-digest object under each item in artifacts.

Artifact inspection fields

Every item in report.files contains an artifact object. When artifact inspection is not requested, artifact.inspected is false and the remaining fields use empty defaults.

With --inspect-artifacts or inspect_artifacts=True, the block includes:

  • archive type, validity, member count, and total uncompressed size
  • wheel record_valid and record_errors
  • console scripts and suspicious entry points
  • native, unexpected top-level, suspicious, oversized, and unusual files
  • parsed Name, Version, and Requires-Dist metadata
  • parsed Wheel-Version, Root-Is-Purelib, and Tag metadata
  • metadata mismatches between PyPI, wheel, and sdist evidence
  • source_files_analyzed and bounded AST parse errors
  • heuristic_findings with category, severity, confidence, score, evidence, source location, artifact name, rule version, estimated false-positive prior, and score threshold
  • native_binaries with PE, ELF, or Mach-O format, architecture, imports, embedded signature presence, entropy, embedded payloads, and parse notes

Every item in report.files also contains a dynamic_analysis object. It is disabled by default. When --dynamic-analysis is set, the object records bounded install analysis, also described in text output as a sandboxed installation probe. The object includes:

  • mode, mode_label, classification, and optional failure_type
  • selected python_version and digest-pinned analyzer image
  • Docker sandbox controls, no-network and non-root execution settings, resource limits, read-only root, read-only artifact mount, and private temp filesystem
  • top-level exit code, bounded output excerpts, and any sandbox error
  • phase results for archive validation, metadata preparation, wheel build, wheel installation, optional import probe, and optional entry-point probe
  • behavioral evidence including child processes, executable paths, file writes, outside-location writes, attempted network connections, credential-path access, persistence-like paths, environment changes, and subprocess arguments

classification: inconclusive or a phase failure must not be interpreted as a clean package. Audit-hook evidence is useful signal, not a sandbox boundary.

Malicious-package heuristic fields

report.malicious_package is always present. Metadata and name checks run for normal package inspection; artifact_analysis indicates whether --inspect-artifacts enabled AST and native-binary inspection.

The aggregate score is bounded to 0-100 and maps to none, low, elevated, high, or critical. Each finding preserves its own score, confidence, estimated false-positive prior, rule version, score threshold, evidence, artifact, and best-effort source location. The JSON field remains false_positive_rate for schema compatibility, but consumers should display it as an estimate until Trustcheck publishes a populated calibration corpus and measured metrics. The assessment records the aggregate score_thresholds and per-rule rule_thresholds active when the report was evaluated.

The assessment is deliberately heuristic. Neither a finding nor a high score is proof of malware. Consumers must preserve the heuristic marker and disclaimer when presenting or transforming this data.

Runtime schema access

from trustcheck import JSON_SCHEMA_ID, JSON_SCHEMA_VERSION, get_json_schema

print(JSON_SCHEMA_VERSION)
print(JSON_SCHEMA_ID)
schema = get_json_schema()

Other machine-readable formats

The JSON contract above remains the lossless trustcheck-native envelope. Standard exports are available for SARIF 2.1.0, CycloneDX 1.6 and 1.7 JSON/XML, SPDX 2.3 JSON, SPDX 3 JSON-LD, and OpenVEX 0.2.0. See Industry output formats for their mappings and stability guarantees.