Run a release audit

Produce a release-evidence pack from a build and read it. This page documents every command in the auditing group, in the order sbomflow help auditing lists them. Each command's section is generated from the command itself — its summary, description and options from the parser, and its reads, writes, exit codes, examples and see-also from the command catalog — so it says exactly what sbomflow <command> --help says. Every example below is executed offline by the test suite, and every non-zero exit code is either produced by an executed probe or carries a recorded reason why no offline probe can produce it.

See the CLI overview for how the thirteen groups fit together and the command reference for every command's options in one place.

Overview#

  • sbomflow audit <dir> --output <dir> — full offline evidence pack for a release.
  • sbomflow analyze <dir> --output <dir> — the analysis stage.
  • sbomflow explain <output> --gap <id> — explain an evidence gap.
  • sbomflow explain <output> --finding <id> — explain an advisory finding.
  • sbomflow explain <output> --gate — explain the release-gate decision.
  • sbomflow explain <output> --warning <code> — explain a scan-warning code and the exact inputs that triggered it in this run (omit the code to list the codes seen). See the Warning codes reference.
  • sbomflow validate — validate a generated output directory.
  • sbomflow next-actions — a sourced worklist for the run you just did; every command it prints is one you can paste and run.

On a large device, validate takes minutes, almost all of it spent checking spdx3-sbom.json against the official SPDX 3.0.1 schema. It announces that step and its expected cost on stderr before starting it, so a long run is distinguishable from a hung one — see validate is taking minutes for the measured figures and how to avoid the cost.

validate is also the tamper check, and a value edited to another JSON type (a string into an array, an object into a number) is a changed artifact like any other: it exits 4 and names the artifact. A check that meets a value of a type it does not read fails that artifact alone, names the check, and lets every other check run. Only when every artifact that check read still holds the bytes the run's completion seal recorded does it end in E099, because then the value is SBOMFlow's own and the fault is a bug to report.

  • sbomflow batch-run <manifest> — run analyze for every product declared in one batch manifest, sequentially. Each job gets its own output directory (enforced before anything runs), every job runs even when an earlier one fails, and the exit code is the worst job's — so a batch never looks healthier than its unhealthiest product. A shell loop does the same thing; this adds per-product isolation and partial-failure aggregation. Every row also carries warnings and console_lines (that job's warning count and the number of lines it was counted out of — a clean job keeps its warnings, not its chatter) and network_posture / network_gates / network_posture_reason. The posture is offline, network_enabled or unknown, read from the configuration that job DECLARES: it says what the job was permitted to reach, never that a socket was or was not opened, and unknown means the declaration could not be read rather than that the job stayed offline. A job that exits hard — an argparse refusal inside the in-process re-invocation raises SystemExit — is recorded as that job's error and the estate continues; Ctrl-C still stops the whole batch.
  • sbomflow next-actions <output-dir> — the release-scoped ship-readiness line (exit N BECAUSE policy X in mode Y) plus the top few outstanding items, with --json for machine use and --limit to widen the list. Aggregation only: it restates the gate's verdict rather than making one, and always exits 0 — the release gate remains the only machine verdict.

Every action names the pack you actually passed and the real decision key, so the printed command is one you can run rather than a template to fill in. When an input genuinely is not knowable from an output directory, the action says so and names where to get it instead of printing a command that would fail. The JSON carries argv as an array alongside the display string, so a caller never has to re-parse a shell line to run one.

Where an action's examples are things you can open on their own — an AI evidence conflict, an AI item with nothing declared about it — each example also carries its own sbomflow explain … --ai-entity <id> command, in example_commands in the JSON and under per example: in the text. Where they are not (a control name, a drift attribute), the action says why it offers none rather than printing a line that would fail, and the category command above it is still the whole answer.

A preserved artifact's review key is printed under its original's file name in the text (e.g. boot-to-idle.psf with the key on the next line, and For boot-to-idle.psf alone: above that artifact's own command), read from preserved-artifacts.json in the directory you passed. sbomflow review does the same in its queue (- boot-to-idle.psf, then the key, then Original verified). The --json document keeps file names out, as before, because it is meant to be shared.

What has LEFT the worklist is recorded too, in terminal_history: count and three examples as before, and now items — every identifier a decision recorded since the analysis run has covered, per category and in total. The worklist is capped because a person reads it; this record is not, because "the finding I decided yesterday — was it handled, or lost?" is a question about the fourth item as much as the first.

A preserved scheme record — a scheme's certificate or a scheme test tool's report, recorded with its kind — whose stated firmware version is not string-equal to the release version this run declares is listed as a scheme_record_names_other_version item. The JSON records list carries each record's review key with the version it states and the version this release declares, and the text shows both beside each example. It is two statements disagreeing, compared as text: the item decides nothing about whether the record still applies, and it stays listed while the two differ, even after a reviewer records a decision about that file (see runtime-and-test-evidence.md).

An entry of the evidence plan in sbomflow.yaml (preserved_artifact_expectations:) that fewer declared rows match than it names — absent, or not_evaluable when rows that state no kind leave the count undecided — is listed in one preserved_artifact_expectation_unmet item. The JSON records list carries each entry's id, kind, minimum, matching row count and state, and the text shows them beside each example. It offers no command: the fix is in sbomflow.yaml or in the records, followed by a new run. It compares a plan you wrote with the rows declared and says nothing about whether the plan is sufficient (see runtime-and-test-evidence.md).

The list also declares what it rests on, in a freshness block:

- live_decisions — the reviewer decision file beside the pack was re-read for this run, so a decision recorded since the analysis run is already reflected, and findings that were ruled on appear under already decided rather than in the worklist; - snapshot_only — no decision file sits beside the pack, so the list rests on the frozen analysis snapshot and names that fact; - snapshot_unreadable_overlay — a decision file is there but could not be read. The list falls back to the snapshot; treat items as possibly stale. This is deliberately not the same state as an absent file.

Each action carries its own freshness_basis too, so a category with no live overlay is labelled rather than borrowing the freshness of the ones that have one.

Each entry in freshness.decision_sources also carries an input_state, because several different facts fall back to the snapshot and must not read alike: absent (nothing is there), unreadable (something is there and its bytes were never seen — a permission, a directory in the file's place, a dangling symlink, a document past the size budget), malformed (the bytes were read and are not that family's decisions — including a file whose entries are not themselves decisions, such as {"key": "accepted"}), conflicted (the file records more than one answer for one key, so none of them is applied) and valid. A rejection_reason travels beside it. Only valid lets an overlay remove anything from the worklist, and even then the removal rests on the recorded status: an entry with no status, an unknown status, or a not_affected without a valid CISA justification and an attributed reviewer is downgraded and stays on the list.

AI and model evidence#

Every AI surface below is a command or flag you can run. Nothing here runs, loads, evaluates or scores a model, and nothing observes runtime behaviour.

  • sbomflow analyze <dir> — static discovery of model artifacts, agents, tools, services and MCP servers, from framework and deployment configuration, dependency files, imports and environment-variable names. Secret values are never recorded, and every detector publishes what it cannot see beside what it can. ai-evidence.json and ai-evidence-map.json are written on every run, including the run that found nothing. Both are experimental artifacts.
  • analyze --ai-manifest <file> / audit --ai-manifest <file> — read your own declaration of the AI in the release. The declaration never overwrites the observation, a disagreement is surfaced and never resolved automatically, and a run without the flag records that nothing was compared. The flag being available does not mean anyone supplied a manifest.
  • analyze --emit-mlbom / --emit-aibom (also on audit) — opt-in AI/ML BOMs: CycloneDX 1.6 ML-BOM and the SPDX 3.0.1 AI profile, linked to the software SBOM rather than copied. The software SBOM itself stays CycloneDX 1.6 and SPDX 2.3.
  • sbomflow explain <output> --ai-entity <id> — explain one AI entity for review. AI-aware release controls are opt-in and off by default; when one is enforced and cannot run, it blocks with its own reason code rather than passing.

Some AI work landed in v0.5.0 as library foundations with no operator path — see Capabilities.

Who this is for: firmware leads, platform teams, estate owners, developers, release managers, QA engineers and programme managers.

sbomflow audit#

Run analyze + full opt-in packs + bundle + validation in one command.

text
One-command release audit: analyze the build, emit the default evidence
artifacts plus the reviewer bundle, and validate everything it wrote.

The audit composes existing deterministic artifacts; it adds no authority
and makes no conformity claim. Human review stays separate and explicit.
FactValue
Groupauditing — Run a release audit
Stabilitystable
Regimeany
Readsthe build directory, optional sbomflow.yaml and local inputs the flags name.
Writesevidence-pack.json (and the default artifacts, into --output); release-gate.json; artifact-manifest.json (the reviewer bundle); evidence-bundle.zip with --zip; stdout (the summary; --json prints JSON)
--output namesa directory
Networkopt-in-network — The default path is offline; only the listed flags/config enable egress. Gates: --use-osv, --use-nvd, --use-kev, --use-epss, --resolve-west-imports, config: osv/nvd enabled with scan.offline=false, config: exploitation.use_kev/use_epss=true with scan.offline=false.
Exit codes0 ok · 1 an enforced gate blocked the release · 2 usage, input, IO or config error · 4 a written artifact failed validation
Machine outputhas-json — read/status surface; one versioned JSON document on stdout

Options

OptionValueDefaultAllowedRequiredHelp
-h, --help(flag)none—noshow this help message and exit
--report-theme{light,dark}lightlight, darknoPalette for generated HTML surfaces (default: light). Print output is always light.
targettargetnoneanyyesProduct source/build directory to scan.
--outputOUTPUTnoneanyyesWhere the evidence outputs are written (directory).
--on-existing-output{overlay,clean,refuse}overlayoverlay, clean, refusenoWhat to do when --output already holds a previous run: overlay (default, write over it), clean (first remove SBOMFlow's own artifacts, never your files), or refuse (write nothing, exit 2).
--configCONFIGnoneanynoPath to a sbomflow.yaml/.json config file.
--storeDIRnoneanynoLocal evidence store holding prior releases of this product. When given, writes cross-release context (offline, read-only): evidence-aging.json (releases since a human last accepted each requirement), finding-regressions.json (resolved findings that reappeared), and carry-forward.json (prior human decisions on findings seen again here).
--product-namePRODUCT_NAMEnoneanynoOverride the product name.
--product-versionPRODUCT_VERSIONnoneanynoOverride the product version.
--product-classCLASSnonedefault, important-class-i, important-class-ii, criticalnoDeclared product class to record. The engine does not classify the product. One of: default, important-class-i, important-class-ii, critical.
--requirement-regime{cra,none}nonecra, nonenoWhich requirement regime this run is executed under: cra (default) derives the CRA Annex I requirement graph, gaps and coverage; none declares that no requirement regime applies, so no requirement is assessed and the run records that declaration. Under none the empty evidence gaps mean NOT ASSESSED, never 'no gaps'. Overrides requirement_regime in sbomflow.yaml.
--as-ofAS_OFnoneanynoISO timestamp to use as 'now' (for reproducible/freshness-pinned runs).
--import-sbomIMPORT_SBOMSnoneanynoImport a local supplier CycloneDX/SPDX JSON SBOM as observed evidence. Repeatable.
--import-custom-manifestIMPORT_CUSTOM_MANIFESTSnoneanynoImport a local SBOMFlow custom manifest (explicit component + dependency evidence). Repeatable; offline.
--supplier-vexSUPPLIER_VEXnoneanynoImport a local supplier OpenVEX/CSAF/CycloneDX VEX document as context only. Repeatable.
--test-resultsTEST_RESULTSnoneanynoAttach a local JUnit XML, TAP or Robot Framework output.xml result file as observed test evidence. Repeatable.
--assessment-findingsPATHnoneanynoA local sbomflow-assessment-findings-v1 file restating the findings an assessment report listed (penetration test, lab evaluation, audit, bug bounty). Writes assessment-findings-ledger.json: each finding stays open until a named reviewer records a decision under assessment:<source>:<id> in the reviews input. Observations only; never a gate input. Offline.
--ai-manifestAI_MANIFESTnoneanynoRead a local declared AI manifest (models, datasets, prompts, services, agents) and record it beside what the scan observed, in ai-evidence.json. Offline: one local file, no lookup. A declaration is what somebody SAID; where it disagrees with an observation both are kept and the disagreement is surfaced for a human, never resolved.
--debian-tracker-snapshotDEBIAN_TRACKER_SNAPSHOTnoneanynoRead a pinned local Debian security-tracker JSON snapshot and annotate findings with the distro's patched-status (no network).
--alpine-secdb-snapshotALPINE_SECDB_SNAPSHOTSnoneanynoRead a pinned local Alpine secdb branch file and annotate findings with the distro's patched-status (no network). Repeatable.
--build-provenanceBUILD_PROVENANCEnoneanynoLocal in-toto/SLSA-shaped statement or DSSE envelope to record.
--build-provenance-public-keyPEM_FILEnoneanynoLocal PEM public key for optional DSSE signature verification (sbomflow[attest]).
--support-policySUPPORT_POLICYnoneanynoLocal support-policy artifact to hash into the release record.
--offline(flag)false—noForce offline mode, overriding config.
--use-osv(flag)false—noQuery the real OSV API (osv.dev) over the network. Off by default.
--use-sample-feed(flag)false—noUse the bundled SYNTHETIC sample advisory feed (CVE-SAMPLE-*). Illustrative demo/example data only, never intelligence about your product.
--osv-snapshotOSV_SNAPSHOTnoneanynoLocal OSV-format advisory snapshot (JSON list, {'vulns': [...]}, JSONL, or an OSV per-ecosystem all.zip) matched offline with the range engine instead of the non-real sample feed. Config: osv.snapshot. Never a live lookup.
--vulndb-dirDIRnoneanynoLocal vulndb store whose active CSAF advisory mirror (vulndb update --source-type csaf-directory) is matched in this run. Offline: that store's index and its active csaf-directory snapshot are read, nothing is fetched, and the store becomes the run's recorded source set. No default is assumed: without it no store is guessed from the working directory or configuration. Refused if it is not a directory, or if another option names a different store.
--osv-timeoutOSV_TIMEOUTnoneanynoOSV request timeout in seconds.
--osv-base-urlOSV_BASE_URLnoneanynoOverride the OSV API base URL.
--osv-cache-dirOSV_CACHE_DIRnoneanynoDirectory to cache OSV records (keyed by id, invalidated by modified time).
--use-nvd(flag)false—noEnrich CVE findings from the live NIST NVD API (network). Off by default.
--nvd-fileNVD_FILEnoneanynoLocal NVD CVE API 2.0 snapshot to enrich offline (no network): a .json file, a .json.gz file, or a .zip holding one .json document.
--nvd-timeoutNVD_TIMEOUTnoneanynoNVD request timeout in seconds.
--nvd-base-urlNVD_BASE_URLnoneanynoOverride the NVD CVE API base URL.
--use-kev(flag)false—noEnrich findings against the live CISA KEV catalog (network). Off by default.
--kev-fileKEV_FILEnoneanynoLocal CISA KEV catalog JSON snapshot to enrich offline (no network).
--use-epss(flag)false—noEnrich findings with live FIRST EPSS scores (network). Off by default.
--epss-fileEPSS_FILEnoneanynoLocal FIRST EPSS snapshot (.csv or .json) to enrich offline (no network).
--resolve-west-imports(flag)false—noResolve Zephyr west 'import:' manifests over the network. Off by default.
--west-name-allowlistWEST_NAME_ALLOWLISTnoneanynoComma-separated project names to include from resolved west imports.
--west-name-blocklistWEST_NAME_BLOCKLISTnoneanynoComma-separated project names to exclude from resolved west imports.
--release-idRELEASE_IDnoneanynoManufacturer/CI-declared release id.
--release-channelRELEASE_CHANNELnoneanynoRelease channel, e.g. stable/beta.
--release-variantRELEASE_VARIANTnoneanynoHardware/software release variant.
--build-idBUILD_IDnoneanynoCI/build-system identifier for this release.
--source-repositorySOURCE_REPOSITORYnoneanynoSource repository URL or local identifier.
--source-revisionSOURCE_REVISIONnoneanynoSource revision used for this release.
--build-started-atBUILD_STARTED_ATnoneanynoBuild start timestamp from CI metadata.
--build-finished-atBUILD_FINISHED_ATnoneanynoBuild completion timestamp from CI metadata.
--support-period-ends-atSUPPORT_PERIOD_ENDS_ATnoneanynoManufacturer-declared support-period end.
--support-promiseKIND=DATEnoneanynoWhat this release promises until DATE, one kind per use: KIND is security_updates, software_maintenance or hardware_availability. Repeatable; replaces release.support_promises for that kind. Each kind is read on its own (a hardware date never answers a security-update question).
--previous-outputPREVIOUS_OUTPUTnoneanynoPrevious SBOMFlow output directory; enables release-drift.json.
--reviewsREVIEWSnoneanynoEvidence reviewer-decisions file to apply; without it (or reviews: in sbomflow.yaml) no decision is applied.
--vulnerability-reviewsVULNERABILITY_REVIEWSnoneanynoVulnerability VEX-triage decisions file to apply.
--reachability-evidenceREACHABILITY_EVIDENCEnoneanynoManufacturer-supplied reachability evidence inputs (context, never a decision).
--tree-sitter-reachability(flag)false—noOpt in to bounded Tree-sitter C/C++ call-context observations (sbomflow[reachability]).
--approvalsAPPROVALSnoneanynoRelease-approval ledger (approvals.json) consulted by the gate.
--waiversWAIVERSnoneanynoReviewer-owned waivers file; an unexpired waiver marks its item 'waived' (still listed).
--require-roleROLEnoneanynoRequired release-approval role (repeatable); additive over a policy profile.
--policyPOLICYnoneanynoStandalone named/versioned release-gate policy profile (.json/.yaml).
--policy-profileNAMEnoneanynoApply a shipped, versioned policy preset by name. Overridden by --policy.
--gate-dry-run(flag)false—noRehearse the gate: evaluate and report fully, mark release-gate.json dry_run, and always exit 0 (never blocks). For CI adoption before enforcing.
--fail-on-gaps(flag)false—noExit non-zero if missing-evidence gaps meet the severity threshold.
--fail-on-unreviewed(flag)false—noExit non-zero if observed evidence has not been human-reviewed.
--fail-on-vulnerabilities(flag)false—noExit non-zero if advisory findings meet the severity threshold.
--fail-on-kev(flag)false—noExit non-zero if any finding is in the CISA KEV catalog (known exploited).
--fail-on-denied-license(flag)false—noExit non-zero if a component declares a license on your policy's license_policy.deny list (engineering context against your own list, never legal advice; only for single valid SPDX expressions).
--fail-on-reachable-vulnerabilities(flag)false—noExit non-zero for source-referenced findings meeting the threshold/policy context.
--fail-on-new-vulnerabilities(flag)false—noExit non-zero when release drift contains new advisory findings.
--fail-on-new-kev(flag)false—noExit non-zero when release drift contains newly known-exploited findings.
--fail-on-new-reachable-vulnerabilities(flag)false—noExit non-zero when release drift contains newly source-referenced findings.
--fail-on-new-critical-or-high(flag)false—noExit non-zero when release drift contains new or escalated critical/high findings.
--fail-on-evidence-regression(flag)false—noExit non-zero when release drift contains new gaps, regressions, or re-review needs.
--fail-on-support-period-missing(flag)false—noExit non-zero when current release metadata lacks support_period_ends_at.
--fail-on-missing-approvals(flag)false—noExit non-zero when required approval roles are unmet and no override is recorded.
--epss-thresholdEPSS_THRESHOLDnoneanynoExit non-zero if any finding's FIRST EPSS score is >= this value (0..1).
--severity-threshold{none,low,medium,high,critical}nonenone, low, medium, high, criticalnoSeverity floor for --fail-on-gaps / --fail-on-vulnerabilities (default: low).
--emit-sarif(flag)false—noAlso write findings.sarif (SARIF 2.1.0) for observed gaps and findings.
--emit-spdx3(flag)false—noAlso write spdx3-sbom.json (SPDX 3.0.1 JSON-LD).
--emit-mlbom(flag)false—noAlso write cyclonedx-mlbom.json (CycloneDX 1.6 ML-BOM; BOM-Linked to the SBOM).
--emit-aibom(flag)false—noAlso write spdx3-aibom.json (SPDX 3.0.1 AI + Dataset profiles).
--emit-traceability(flag)false—noAlso write traceability.json (cross-entity node/edge index; a derived view).
--share-profile{importer,distributor,customer}noneimporter, distributor, customernoAlso write a redacted evidence-sharing pack for the chosen profile (sharing-pack.json/html/zip). Adds no authority and no conformity claim.
--emit-metrics(flag)false—noAlso write local metrics.json (aggregate counts, gate state, phase durations, tool metadata, and declared release metadata).
--emit-issues-csv(flag)false—noAlso write issues.csv, a spreadsheet-friendly projection of issues.json.
--emit-pdf(flag)false—noAlso write evidence-summary.pdf and include it in the bundle.
--zip(flag)false—noWrite evidence-bundle.zip.
--scan-cache-dirSCAN_CACHE_DIRnoneanynoOptional content-addressed scan cache for faster repeat scans of unchanged files.
--scan-jobsN1anynoHash files with N parallel workers (default 1); ignored with --scan-cache-dir.
--strict(flag)false—noEnforce the manufacturer's strict policy set. This is not a CRA conformity determination.
--break-stale-lock(flag)false—noRemove a provably-stale .sbomflow.lock (crashed run) from the output directory before running. Never automatic; confirm no other run is active first.
--json(flag)false—noEmit one machine-readable summary.

Examples

Run the full offline evidence pack for one release.

sh
sbomflow audit . --output out

Also write the deterministic evidence-bundle.zip to hand over.

sh
sbomflow audit . --output evidence --zip

Enforce the evidence-gap gate; it blocks this demo and exits 1 with every artifact written. Exits 1.

sh
sbomflow audit . --output evidence --fail-on-gaps

Print one machine-readable summary instead of the text report.

sh
sbomflow audit . --output evidence --json

Audit with no requirement regime assessed.

sh
sbomflow audit . --output evidence --requirement-regime none

Write one release's full offline evidence pack into evidence, the directory the first steps read.

sh
sbomflow audit . --output evidence

See also: sbomflow analyze, sbomflow review, sbomflow bundle, sbomflow explain, sbomflow help auditing, sbomflow help goal sign-off.

sbomflow analyze#

Scan a product directory and write its evidence pack (audit adds the bundle).

text
Scan one product/build directory and write the default deterministic
evidence artifacts (evidence pack, SBOMs, coverage, gate, report, ...).
`sbomflow audit` wraps this with the reviewer bundle and validation.
FactValue
Groupauditing — Run a release audit
Stabilitystable
Regimeany
Readsthe target directory, optional sbomflow.yaml and local inputs the flags name.
Writesevidence-pack.json (and the default artifacts, into --output); release-gate.json; release-record.json; scan-warnings.json
--output namesa directory
Networkopt-in-network — The default path is offline; only the listed flags/config enable egress. Gates: --use-osv, --use-nvd, --use-kev, --use-epss, --resolve-west-imports, config: osv/nvd enabled with scan.offline=false, config: exploitation.use_kev/use_epss=true with scan.offline=false.
Exit codes0 ok · 1 an enforced gate blocked the release · 2 usage, input, IO or config error · 5 --strict matched a scan warning
Machine outputartifact-suffices — writes the full evidence artifact set (SBOM, findings, gate, and under the cra regime the gaps and CRA report…); the files are the API

Options

OptionValueDefaultAllowedRequiredHelp
-h, --help(flag)none—noshow this help message and exit
--report-theme{light,dark}lightlight, darknoPalette for generated HTML surfaces (default: light). Print output is always light.
targettargetnoneanyyesProduct source/build directory to scan.
--outputOUTPUTnoneanyyesWhere the evidence outputs are written (directory).
--on-existing-output{overlay,clean,refuse}overlayoverlay, clean, refusenoWhat to do when --output already holds a previous run: overlay (default, write over it), clean (first remove SBOMFlow's own artifacts, never your files), or refuse (write nothing, exit 2).
--configCONFIGnoneanynoPath to a sbomflow.yaml/.json config file.
--storeDIRnoneanynoLocal evidence store holding prior releases of this product. When given, writes cross-release context (offline, read-only): evidence-aging.json (releases since a human last accepted each requirement), finding-regressions.json (resolved findings that reappeared), and carry-forward.json (prior human decisions on findings seen again here).
--product-namePRODUCT_NAMEnoneanynoOverride the product name.
--product-versionPRODUCT_VERSIONnoneanynoOverride the product version.
--product-classCLASSnonedefault, important-class-i, important-class-ii, criticalnoDeclared product class to record. The engine does not classify the product. One of: default, important-class-i, important-class-ii, critical.
--requirement-regime{cra,none}nonecra, nonenoWhich requirement regime this run is executed under: cra (default) derives the CRA Annex I requirement graph, gaps and coverage; none declares that no requirement regime applies, so no requirement is assessed and the run records that declaration. Under none the empty evidence gaps mean NOT ASSESSED, never 'no gaps'. Overrides requirement_regime in sbomflow.yaml.
--use-osv(flag)false—noQuery the real OSV API (osv.dev) over the network. Off by default.
--use-sample-feed(flag)false—noUse the bundled SYNTHETIC sample advisory feed (CVE-SAMPLE-*). Illustrative demo/example data only, never intelligence about your product: artifacts mark it synthetic and it never counts as usable intelligence. Without a real source (--use-osv/--osv-snapshot) and without this flag, no advisory matching is performed at all.
--osv-snapshotOSV_SNAPSHOTnoneanynoLocal OSV-format advisory snapshot (JSON list, {'vulns': [...]}, JSONL, or an OSV per-ecosystem all.zip) matched offline with the range engine instead of the non-real sample feed. Config: osv.snapshot. Never a live lookup.
--vulndb-dirDIRnoneanynoLocal vulndb store whose active CSAF advisory mirror (vulndb update --source-type csaf-directory) is matched in this run. Offline: that store's index and its active csaf-directory snapshot are read, nothing is fetched, and the store becomes the run's recorded source set. No default is assumed: without it no store is guessed from the working directory or configuration. Refused if it is not a directory, or if another option names a different store.
--offline(flag)false—noForce offline mode (never query OSV or resolve west imports), overriding config.
--resolve-west-imports(flag)false—noResolve Zephyr west 'import:' directives over the network (like --use-osv): fetch each imported manifest and add its modules as components. Off by default; dropped under --offline.
--west-import-dirDIRnoneanynoResolve Zephyr west 'import:' directives from a local mirror instead of the network: DIR holds one checkout per project (DIR/<project>/west.yml). Stays OFFLINE and never falls back to the network. Mutually exclusive with --resolve-west-imports.
--west-name-allowlistWEST_NAME_ALLOWLISTnoneanynoComma-separated project names to include from resolved west imports.
--west-name-blocklistWEST_NAME_BLOCKLISTnoneanynoComma-separated project names to exclude from resolved west imports.
--osv-timeoutOSV_TIMEOUTnoneanynoOSV request timeout in seconds.
--osv-base-urlOSV_BASE_URLnoneanynoOverride the OSV API base URL.
--osv-cache-dirOSV_CACHE_DIRnoneanynoDirectory to cache OSV records (keyed by id, invalidated by modified time).
--scan-cache-dirSCAN_CACHE_DIRnoneanynoDirectory for an optional content-addressed scan cache that speeds repeat scans of unchanged files. The cache only speeds up scanning; output is byte-identical with or without it.
--scan-jobsN1anynoHash files with N parallel workers for large trees (default 1). Output is byte-identical to a single-threaded scan; ignored when --scan-cache-dir is set.
--use-nvd(flag)false—noEnrich CVE findings from the live NIST NVD API (network). Off by default.
--nvd-fileNVD_FILEnoneanynoLocal NVD CVE API 2.0 snapshot to enrich offline (no network): a .json file, a .json.gz file, or a .zip holding one .json document.
--nvd-timeoutNVD_TIMEOUTnoneanynoNVD request timeout in seconds.
--nvd-base-urlNVD_BASE_URLnoneanynoOverride the NVD CVE API base URL.
--policyPOLICYnoneanynoStandalone named/versioned release-gate policy profile (.json/.yaml).
--policy-profileNAMEnoneanynoApply a shipped, versioned policy preset by name (cra-critical, cra-default, cra-important, strict-ci). Overridden by --policy; CLI --fail-on-* flags are additive.
--use-kev(flag)false—noEnrich findings against the live CISA KEV catalog (network). Off by default.
--kev-fileKEV_FILEnoneanynoLocal CISA KEV catalog JSON snapshot to enrich offline (no network).
--use-epss(flag)false—noEnrich findings with live FIRST EPSS scores (network). Off by default.
--epss-fileEPSS_FILEnoneanynoLocal FIRST EPSS snapshot (.csv or .json) to enrich offline (no network).
--reviewsREVIEWSnoneanynoEvidence reviewer-decisions file to apply; without it (or reviews: in sbomflow.yaml) no decision is applied.
--vulnerability-reviewsVULNERABILITY_REVIEWSnoneanynoPath to a vulnerability VEX-triage decisions file (for --emit-vex).
--reachability-evidenceREACHABILITY_EVIDENCEnoneanynoPath to manufacturer-supplied reachability evidence inputs.
--ai-manifestAI_MANIFESTnoneanynoRead a local declared AI manifest (models, datasets, prompts, services, agents) and record it beside what the scan observed, in ai-evidence.json. Offline: one local file, no lookup. A declaration is what somebody SAID; where it disagrees with an observation both are kept and the disagreement is surfaced for a human, never resolved.
--debian-tracker-snapshotDEBIAN_TRACKER_SNAPSHOTnoneanynoRead a pinned local Debian security-tracker JSON snapshot and annotate findings with the distro's patched-status (no network).
--alpine-secdb-snapshotALPINE_SECDB_SNAPSHOTSnoneanynoRead a pinned local Alpine secdb branch file and annotate findings with the distro's patched-status (no network). Repeatable.
--tree-sitter-reachability(flag)false—noOpt in to bounded Tree-sitter C/C++ call-context observations. Requires sbomflow[reachability]; regex scanning remains the baseline.
--ssvc-contextSSVC_CONTEXTnoneanynoPath to manufacturer SSVC context (Automatable / Mission & Well-being defaults and optional per-finding overrides) for --emit-ssvc.
--incident-awareness-atINCIDENT_AWARENESS_ATnoneanynoInstant the manufacturer recorded becoming aware. Starts the CRA Article 14 24-hour and 72-hour windows shown in --emit-incident-report. Recorded by you; never inferred, and never a decision that anything is reportable.
--incident-measure-available-atINSTANTnoneanynoInstant a corrective or mitigating measure became available. Starts the Article 14(2)(c) 14-day final-report window (actively exploited vulnerability track) — which does NOT run from awareness.
--incident-notification-submitted-atINSTANTnoneanynoInstant the manufacturer recorded submitting the Article 14(4)(b) incident notification, elsewhere. Starts the Article 14(4)(c) one-month final-report window (severe-incident track). Recording it here is a note to yourself; SBOMFlow never submits anything.
--import-sbomIMPORT_SBOMSnoneanynoImport a local supplier CycloneDX/SPDX JSON SBOM as observed component evidence. Repeatable; offline and local-file-only.
--import-custom-manifestIMPORT_CUSTOM_MANIFESTSnoneanynoImport a local SBOMFlow custom manifest (sbomflow-custom-manifest v1): explicit component + dependency evidence a manufacturer declares directly. Repeatable; offline and local-file-only. See docs/CUSTOM_MANIFEST.md.
--supplier-vexSUPPLIER_VEXnoneanynoImport a local supplier OpenVEX/CSAF/CycloneDX JSON VEX document as context for matching findings. Repeatable; never suppresses gates by itself.
--test-resultsTEST_RESULTSnoneanynoAttach a local JUnit XML, TAP or Robot Framework output.xml test-result file as observed security-test evidence for human review. Repeatable; offline only.
--assessment-findingsPATHnoneanynoA local sbomflow-assessment-findings-v1 file restating the findings an assessment report listed (penetration test, lab evaluation, audit, bug bounty). Writes assessment-findings-ledger.json: each finding stays open until a named reviewer records a decision under assessment:<source>:<id> in the reviews input. Observations only; never a gate input. Offline.
--as-ofAS_OFnoneanynoISO timestamp to use as 'now' (for reproducible/freshness-pinned runs).
--release-idRELEASE_IDnoneanynoManufacturer/CI-declared release id.
--release-channelRELEASE_CHANNELnoneanynoRelease channel, e.g. stable/beta.
--release-variantRELEASE_VARIANTnoneanynoHardware/software release variant.
--build-idBUILD_IDnoneanynoCI/build-system identifier for this release.
--source-repositorySOURCE_REPOSITORYnoneanynoSource repository URL or local identifier.
--source-revisionSOURCE_REVISIONnoneanynoSource revision used for this release.
--build-started-atBUILD_STARTED_ATnoneanynoBuild start timestamp from CI metadata.
--build-finished-atBUILD_FINISHED_ATnoneanynoBuild completion timestamp from CI metadata.
--support-period-ends-atSUPPORT_PERIOD_ENDS_ATnoneanynoManufacturer-declared support-period end.
--support-promiseKIND=DATEnoneanynoWhat this release promises until DATE, one kind per use: KIND is security_updates, software_maintenance or hardware_availability. Repeatable; replaces release.support_promises for that kind. Each kind is read on its own (a hardware date never answers a security-update question).
--support-policySUPPORT_POLICYnoneanynoLocal support-policy artifact to hash into the release record.
--previous-outputPREVIOUS_OUTPUTnoneanynoPrevious SBOMFlow output directory used to emit release-drift.json.
--build-provenanceBUILD_PROVENANCEnoneanynoLocal in-toto/SLSA-shaped statement or DSSE envelope to record.
--build-provenance-public-keyPEM_FILEnoneanynoLocal PEM public key for optional DSSE build-provenance signature verification. Requires sbomflow[attest].
--gate-dry-run(flag)false—noRehearse the gate: evaluate and report fully, mark release-gate.json dry_run, and always exit 0 (never blocks). For CI adoption before enforcing.
--fail-on-gaps(flag)false—noExit non-zero if missing-evidence gaps meet the severity threshold.
--fail-on-unreviewed(flag)false—noExit non-zero if observed evidence has not been human-reviewed.
--fail-on-vulnerabilities(flag)false—noExit non-zero if advisory findings meet the severity threshold.
--fail-on-kev(flag)false—noExit non-zero if any finding is in the CISA KEV catalog (known exploited).
--fail-on-denied-license(flag)false—noExit non-zero if a component declares a license on your policy's license_policy.deny list (engineering context against your own list, never legal advice; only for single valid SPDX expressions).
--fail-on-reachable-vulnerabilities(flag)false—noExit non-zero for source-referenced advisory findings that meet the severity threshold or enabled KEV/EPSS policy context.
--fail-on-new-vulnerabilities(flag)false—noExit non-zero when release drift contains new advisory findings.
--fail-on-new-kev(flag)false—noExit non-zero when release drift contains newly known-exploited findings.
--fail-on-new-reachable-vulnerabilities(flag)false—noExit non-zero when release drift contains newly source-referenced findings.
--fail-on-new-critical-or-high(flag)false—noExit non-zero when release drift contains new or escalated critical/high findings.
--fail-on-evidence-regression(flag)false—noExit non-zero when release drift contains new gaps, status regressions, or re-review needs.
--fail-on-support-period-missing(flag)false—noExit non-zero when current release metadata lacks support_period_ends_at.
--fail-on-missing-approvals(flag)false—noExit non-zero when required release-approval roles are unmet (or a separation-of-duties violation exists) and no active override is recorded.
--require-roleROLEnoneanynoRequired release-approval role (repeatable); additive over a policy profile.
--approvalsAPPROVALSnoneanynoRelease-approval ledger (approvals.json) consulted by the gate.
--waiversWAIVERSnoneanynoReviewer-owned waivers file (waivers.json) consulted by the gate. An unexpired waiver moves its exact gap/finding to 'waived' (still listed); it never accepts evidence, sets VEX, or claims conformity.
--epss-thresholdEPSS_THRESHOLDnoneanynoExit non-zero if any finding's FIRST EPSS score is >= this value (0..1).
--severity-threshold{none,low,medium,high,critical}nonenone, low, medium, high, criticalnoSeverity floor for --fail-on-gaps / --fail-on-vulnerabilities (default: low).
--emit-vex(flag)false—noAlso write vex.json (OpenVEX; all statements default to under_investigation).
--emit-vdr(flag)false—noAlso write cyclonedx-vdr.json (CycloneDX Vulnerability Disclosure Report: every known finding, including untriaged ones, which carry no analysis).
--emit-techdoc(flag)false—noAlso write the CRA Annex VII technical-documentation pack index and UNSIGNED DRAFT EU declaration workspace.
--emit-incident-report(flag)false—noAlso write the CRA Article 14 UNSIGNED DRAFT incident/vulnerability notification pack (early warning / notification / final report). SBOMFlow never files, transmits, or submits any report.
--emit-ssvc(flag)false—noAlso write ssvc.json: a suggested CISA SSVC action priority (Track / Track* / Attend / Act) per finding for human review. Not a remediation mandate and not a conformity claim.
--emit-sarif(flag)false—noAlso write findings.sarif (SARIF 2.1.0) for observed gaps and vulnerability findings. SARIF level is severity, not a release decision.
--emit-spdx3(flag)false—noAlso write spdx3-sbom.json (SPDX 3.0.1 JSON-LD). SPDX 2.3 remains the default SBOM for broad interoperability.
--emit-mlbom(flag)false—noAlso write cyclonedx-mlbom.json: a CycloneDX 1.6 ML-BOM over the AI evidence graph. Links to the software SBOM by BOM-Link; never copies its components. An inventory, not a safety or conformity claim.
--emit-aibom(flag)false—noAlso write spdx3-aibom.json: an SPDX 3.0.1 AI + Dataset profile document over the same AI evidence graph. Add --emit-spdx3 to have it import that document's product element instead of restating it.
--drift-html(flag)false—noWhen release drift is produced (with --previous-output), also write release-drift.html, a human-readable release-diff report.
--emit-traceability(flag)false—noAlso write traceability.json: a cross-entity node/edge index linking product, release, components, vulnerabilities, requirements, evidence, gaps, issues, and scanned source bytes. A derived view that adds no claims.
--emit-issues-csv(flag)false—noAlso write issues.csv, a spreadsheet-friendly projection of issues.json. This is a data export only, not a release or legal decision.
--emit-pdf(flag)false—noAlso write evidence-summary.pdf, a deterministic text summary for auditor handoff. HTML/JSON stay canonical; the PDF adds no claims.
--emit-bundle(flag)false—noAlso write evidence-bundle.json/html for reviewer handoff.
--share-profile{importer,distributor,customer}noneimporter, distributor, customernoAlso write a redacted evidence-sharing pack for the chosen profile (sharing-pack.json/html/zip): a documented SBOM subset plus coverage summary, declaration-draft status, and support period. Internal reviewer notes are redacted; it adds no authority and no conformity claim.
--emit-metrics(flag)false—noAlso write local metrics.json with aggregate counts, gate state, phase durations, tool metadata, and declared release metadata (no source content, credentials, or contact details; inspect release metadata before sharing).
--break-stale-lock(flag)false—noRemove a provably-stale .sbomflow.lock (crashed run) from the output directory before running. Never automatic; confirm no other run is active first.
--strict[STRICT_WARNINGS]noneanynoTreat scan warnings as errors after artifacts are written. Use --strict for any warning except the disclosure-only scan_directory_excluded_by_marker, or --strict=code1,code2 to scope by warning code (naming that code counts it) (distinct exit code 5).

Examples

Scan a source tree and write the evidence artifacts.

sh
sbomflow analyze . --output out --product-name Gateway --product-version 2.4.1

Refuse to write into a directory that already holds a run. Exits 2.

sh
sbomflow analyze . --output out --on-existing-output refuse

Emit a VEX document alongside the pack, for downstream consumers.

sh
sbomflow analyze . --output out --emit-vex

Write the SBOMs with no requirement regime assessed.

sh
sbomflow analyze . --output out --requirement-regime none

Compare with the previous release's pack and write the drift report as HTML too.

sh
sbomflow analyze . --output out --previous-output out-prev --drift-html

See also: sbomflow audit, sbomflow review, sbomflow explain, sbomflow compare-releases, sbomflow help auditing, sbomflow help goal sbom.

sbomflow batch-run#

Run analyze across every product declared in one batch manifest.

text
Run `analyze` for each job in a batch manifest, sequentially, and
aggregate the outcomes. Ergonomics over a shell loop: per-product
isolation and partial-failure aggregation, not new capability. The
exit is 0 only if every job exited 0, else the worst job's code.
FactValue
Groupauditing — Run a release audit
Stabilitystable
Regimeany
Readsa batch manifest and each job's source tree.
Writesevidence-pack.json (one pack per job, in its own directory); stdout (the summary; --json prints JSON)
Networkopt-in-network — Runs analyze per job, so it inherits analyze's class: the default path is offline, but a JOB'S OWN CONFIG can enable egress for that job. The batch adds no network flags itself. Gates: each job's own config: osv/nvd enabled with scan.offline=false, each job's own config: exploitation.use_kev/use_epss=true with scan.offline=false.
Exit codes0 every job exited 0 · 1 the worst job's enforced gate blocked it · 2 manifest refused, or the worst job exited 2
Machine outputhas-json — one versioned batch summary on stdout; each job's own output is captured so the document stays parseable, and every row carries that job's warning count (with the line count it was taken out of) plus its declared network posture

Options

OptionValueDefaultAllowedRequiredHelp
-h, --help(flag)none—noshow this help message and exit
manifestmanifestnoneanyyesBatch manifest declaring the jobs to run.
--json(flag)false—noEmit the batch summary as JSON.

Examples

Analyze every product the manifest declares, one after another.

sh
sbomflow batch-run estate/estate.yaml

Print the batch summary as JSON, one row per job.

sh
sbomflow batch-run estate/estate.yaml --json

Refuse a file that is not a batch manifest. Exits 2.

sh
sbomflow batch-run estate/products/sensor/requirements.txt

See also: sbomflow analyze, sbomflow portfolio, sbomflow dashboard.

sbomflow validate#

Validate a generated evidence output directory.

text
Check one analyze or audit output directory: every artifact it holds is parsed
and checked against its published schema, the recorded hashes are re-verified,
and the run's completion seal is compared with the bytes on disk. It writes
nothing. A malformed or changed artifact exits 4, and so does a pack whose
recorded producer (0.5.0 or later) always writes run-completion.json but has
none; a directory that cannot be used exits 2.
FactValue
Groupauditing — Run a release audit
Stabilitystable
Regimeany
Readsan existing analyze or audit output directory.
Writesstdout (the report; --json prints JSON)
Networkoffline — This command has no network-capable path.
Exit codes0 every present artifact is valid · 2 the directory is missing or unusable · 4 an artifact is malformed or changed, or a pack whose producer always writes run-completion.json has none
Machine outputhas-json — read/status surface; one versioned JSON document on stdout

Options

OptionValueDefaultAllowedRequiredHelp
-h, --help(flag)none—noshow this help message and exit
EVIDENCE_DIREVIDENCE_DIRnoneanyyesDirectory produced by 'analyze'.
--json(flag)false—noMachine-readable report on stdout (schema_version sbomflow-validate-report-v1); same exit codes as the human output.

Examples

Check that an output directory is a complete, well-formed run.

sh
sbomflow validate out

Print the same report as one JSON document, with the same exit.

sh
sbomflow validate out --json

Refuse a pack whose evidence-pack.json fails its schema. Exits 4.

sh
sbomflow validate broken-evidence

See also: sbomflow audit, sbomflow verify-bundle, sbomflow store verify, sbomflow help exit.

sbomflow explain#

Explain one gap, finding, gate decision, warning or preserved artifact from existing artifacts.

text
Print a sourced, human-readable explanation of one gap, finding, the
gate decision, a scan-warning code or a preserved artifact - composed
purely from existing artifacts (no AI).
FactValue
Groupauditing — Run a release audit
Stabilitystable
Regimeany
Readsan existing analyze or audit output directory; --explain-terms needs none.
Writesstdout (the explanation; nothing is written)
Networkoffline — This command has no network-capable path.
Exit codes0 ok · 2 unknown id or missing artifact
Machine outputhuman-only-by-design — renders a prose explanation composed from artifacts that are already machine-readable on disk

Options

OptionValueDefaultAllowedRequiredHelp
-h, --help(flag)none—noshow this help message and exit
[EVIDENCE_DIR][EVIDENCE_DIR]noneanynoDirectory produced by 'analyze' (not needed for --explain-terms).
--gapGAP_IDnoneanynoExplain this evidence gap id.
--findingVULN_IDnoneanynoExplain this advisory finding id/alias.
--gate(flag)false—noExplain release-gate.json.
--ai-entityENTITY_IDnoneanynoExplain one AI evidence entity end to end: what was observed, what was declared, where each fact came from, and what is being asked of a reviewer. A unique id prefix is accepted.
--preserved-artifactKEYnoneanynoExplain one preserved artifact in this run: its declared record, the original, the identity the record states, the run's checks, the review decision and the files that name it. A full review key or a unique digest prefix of at least 12 hex characters.
--explain-terms[TERM]noneanynoPlain-language definitions of the core vocabulary (SBOM, VEX, CVSS, purl, gate, KEV, EPSS, SSVC, ...). Omit TERM for all of them; needs no output directory.
--warning[CODE]noneanynoExplain a scan-warning code and this run's occurrences (omit CODE to list the codes seen in this run).

Examples

Explain why the release gate decided what it decided.

sh
sbomflow explain out --gate

Explain one scan-warning code, sourced from the catalog.

sh
sbomflow explain out --warning unparseable_manifest

Explain one advisory finding: where it matched and what a reviewer decided.

sh
sbomflow explain out --finding CVE-SAMPLE-OPENSSL-001

List the warning codes this run actually emitted.

sh
sbomflow explain out --warning

Define a term; no output directory is needed.

sh
sbomflow explain --explain-terms kev

Explain one preserved artifact in a run that declared it: its record, original, stated identity, the run's checks, the review decision and the files that name it.

sh
sbomflow explain sensor-evidence --preserved-artifact c640b5514933

See also: sbomflow review, sbomflow next-actions, sbomflow help, sbomflow help warning.

sbomflow next-actions#

Release-scoped ship-readiness line plus the top few outstanding actions.

text
Answer "is this release ready, and what do I deal with first?" by
aggregating facts already in an output directory. Aggregation only -
it invents nothing, decides nothing, and never says ship/do-not-ship.
FactValue
Groupauditing — Run a release audit
Stabilitystable
Regimeany
Readsan existing analyze or audit output directory.
Writesstdout (the worklist; --json prints JSON)
Networkoffline — This command has no network-capable path.
Exit codes0 ok, even with actions outstanding · 2 missing or unusable directory
Machine outputhas-json — one versioned next-actions document on stdout; aggregation only, never a decision

Options

OptionValueDefaultAllowedRequiredHelp
-h, --help(flag)none—noshow this help message and exit
EVIDENCE_DIREVIDENCE_DIRnoneanyyesDirectory produced by 'analyze' or 'audit'.
--json(flag)false—noEmit the next-actions document as JSON.
--limitLIMITnoneanynoHow many actions to surface (default 3).

Examples

Print the ship-readiness line and the three actions to deal with first.

sh
sbomflow next-actions out

Print the next-actions document as JSON.

sh
sbomflow next-actions out --json

Surface five actions instead of three.

sh
sbomflow next-actions out --limit 5

See also: sbomflow explain, sbomflow review, sbomflow report freshness.

sbomflow report#

Derived, read-only planning reports composed from a finished run.

text
Read-only planning reports composed from a finished run. Each verb reads
artifacts that are already on disk and decides nothing; name a verb, or the
group prints its usage and exits 2.
FactValue
Groupauditing — Run a release audit
Stabilitystable
Regimeany
Readsnothing itself; its verb reads a finished output directory.
Writesnothing itself; its verb's help names what it writes
Networkoffline — This command has no network-capable path.
Exit codes0 a verb ran and returned 0 · 2 no verb, or the verb refused
Machine outputhuman-only-by-design — group dispatcher: prints usage/guidance only; the machine surfaces are its nested verbs

Options

OptionValueDefaultAllowedRequiredHelp
-h, --help(flag)none—noshow this help message and exit

Examples

Print what lapses next in a finished run, evaluated at a pinned time.

sh
sbomflow report freshness out --as-of 2026-07-01T00:00:00Z

The same horizon as JSON, flagging items that lapse within 30 days.

sh
sbomflow report freshness out --json --as-of 2026-07-01T00:00:00Z --horizon-days 30

Name no verb: print the report group's usage and exit 2. Exits 2.

sh
sbomflow report

See also: sbomflow report freshness, sbomflow next-actions.

sbomflow report freshness#

What goes stale next: one dated horizon composed from a run's artifacts.

text
Compose one freshness horizon from a finished output directory: accepted
evidence validity windows, advisory-snapshot staleness, waiver expiries,
and the support-period end — all the dated things that lapse, soonest
first.

Read-only and offline. Planning context, not a decision: it changes no
review state and suppresses no gate. Writes freshness-horizon.json into
the directory.
FactValue
Groupauditing — Run a release audit
Stabilitystable
Regimeany
Readsa finished analyze or audit output directory.
Writesfreshness-horizon.json, into the directory; stdout (the horizon; --json prints JSON)
Networkoffline — This command has no network-capable path.
Exit codes0 ok · 2 missing or unusable directory
Machine outputhas-json — read/status surface; one versioned JSON document on stdout

Options

OptionValueDefaultAllowedRequiredHelp
-h, --help(flag)none—noshow this help message and exit
EVIDENCE_DIREVIDENCE_DIRnoneanyyesA finished analyze/audit output directory.
--as-ofAS_OFnoneanynoEvaluate the horizon at this ISO-8601 UTC time (default: now).
--horizon-daysHORIZON_DAYS90anynoFlag items lapsing within this many days as expiring_soon (default: 90).
--json(flag)false—noEmit JSON to stdout.

Examples

Print what lapses next, evaluated at a pinned time.

sh
sbomflow report freshness out --as-of 2026-07-01T00:00:00Z

The same horizon as JSON, flagging items that lapse within 30 days.

sh
sbomflow report freshness out --json --as-of 2026-07-01T00:00:00Z --horizon-days 30

Look a year ahead: every dated item lapsing within 365 days is flagged.

sh
sbomflow report freshness out --as-of 2026-07-01T00:00:00Z --horizon-days 365

See also: sbomflow next-actions, sbomflow recheck, sbomflow vulndb retention.