chainsaw sbom
Software Bill of Materials commands
Software Bill of Materials commands
| Subcommand | What it does |
|---|---|
chainsaw sbom diff | Diff two SBOMs (CycloneDX or in-toto), reporting added, removed, and version-changed components |
chainsaw sbom export | Export org SBOM in CycloneDX format |
chainsaw sbom verify | Verify a Sigstore-signed CycloneDX SBOM bundle |
chainsaw sbom vex | CycloneDX VEX commands |
chainsaw sbom vex export | Export org exceptions as a CycloneDX 1.6 VEX document |
chainsaw sbom [command]
chainsaw sbom diff
Diff two SBOMs (CycloneDX or in-toto), reporting added, removed, and version-changed components
chainsaw sbom diff <a.json> <b.json> [flags]
Diff two SBOM files. The format of each input is auto-detected: CycloneDX documents (bomFormat=“CycloneDX”) and in-toto Statements wrapping a CycloneDX predicate are both accepted. Both inputs must be the same format — mixing CycloneDX and in-toto in a single diff is not supported in this iteration.
JSON output (–format json) is a versioned envelope:
{ “schemaVersion”: “chainsaw.sbomdiff/v1”, “added”: [ {“name”,“version”,“type”,“ecosystem”,“purl”}, … ], “removed”: [ … same shape … ], “changed”: [ {“name”,“type”,“ecosystem”,“oldVersion”,“newVersion”}, … ] }
The three arrays are always present and always arrays — an empty diff emits [] , never null, so a consumer can iterate unconditionally. Pin on schemaVersion: it is bumped only for a backward-incompatible change, and additive fields keep the same version.
Changed in v0.20.3: keys were previously the Go field names (“Added”, “Name”, “OldVersion”) and an empty diff emitted null. Scripts written against a pre-0.20.3 binary need updating.
Flags
| Flag | Type | Default | Description |
|---|---|---|---|
--format | string | text | Output format: text or json |
The global flags apply here too.
chainsaw sbom export
Export org SBOM in CycloneDX format
chainsaw sbom export [flags]
Flags
| Flag | Type | Default | Description |
|---|---|---|---|
--ecosystem | string | — | Filter by ecosystem (e.g. npm, pip, maven) |
--format | string | cyclonedx | SBOM format: cyclonedx (default) or spdx (SPDX 2.3, rendered client-side from the CycloneDX document) |
--package | string | — | Filter by package name@version |
--with-attribution | bool | — | Include per-component attribution properties (chainsaw:attribution:*) derived from existing audit data. Overrides the server’s sbom.attribution_enabled config for this export. |
The global flags apply here too.
chainsaw sbom verify
Verify a Sigstore-signed CycloneDX SBOM bundle
chainsaw sbom verify [flags]
Verify a Sigstore-signed CycloneDX SBOM bundle against the SBOM document it attests to. Confirms:
- The bundle’s signature validates against the live Sigstore trust root (Rekor + Fulcio).
- The in-toto subject digest matches sha256(canonical(SBOM)).
- The predicateType is CycloneDX (not a different in-toto predicate).
On success the verified signer identity is printed: source repository URL, builder OIDC subject, and OIDC issuer. Exits non-zero on any failure so CI pipelines can gate on the verify step.
Flags
| Flag | Type | Default | Description |
|---|---|---|---|
--bom | string | — | Path to the CycloneDX SBOM JSON file the bundle attests to (required) |
--bundle | string | — | Path to the Sigstore bundle JSON file (required) |
--cache-dir | string | — | Optional Sigstore bundle cache directory (defaults to no caching) |
--cache-ttl | duration | 24h0m0s | Cache entry TTL when –cache-dir is set |
--json | bool | — | Emit machine-readable JSON instead of the human summary |
The global flags apply here too.
chainsaw sbom vex
CycloneDX VEX commands
chainsaw sbom vex [command]
chainsaw sbom vex export
Export org exceptions as a CycloneDX 1.6 VEX document
chainsaw sbom vex export [flags]
Export active exceptions as CycloneDX VEX statements. Each active exception with a CVE reference becomes a vulnerabilities[] entry whose analysis.state reflects Chainsaw’s stance:
decision=allow → exploitable, response=[will_not_fix] decision=monitor → in_triage
A Chainsaw exception is a risk acceptance: the vulnerable package is present and you have chosen to ship it. That is exploitable, not not_affected — encoding it as not_affected tells a downstream scanner the vulnerable code is absent from your product and it will suppress the finding.
The exception’s note rides along in analysis.detail verbatim. It is not parsed into a justification: only you can assert reachability, and Chainsaw will not make that claim on your behalf.
Denied and expired exceptions are excluded, as are exceptions still awaiting approval — an unapproved exception grants nothing at enforcement time, so it must not be published as a compliance statement.
Flags
| Flag | Type | Default | Description |
|---|---|---|---|
--org | string | — | Org id (defaults to configured org) |
-o, --output | string | — | Write VEX to file instead of stdout |
The global flags apply here too.