Skip to content

Artifacts reference

The generated SBOM is CycloneDX 1.6 JSON. An SPDX 2.3 JSON copy, converted from the final CycloneDX BOM, is produced by --spdx during a CLI scan or on demand from the results screen in the UI. Both paths run the same conversion and give the same file. CycloneDX remains the primary format, and CycloneDX-only data (vulnerabilities, bomlens:* properties) is not carried over.

The filename is {Project}_{Version}_bom.json (e.g. MyApp_1.0.0_bom.json).

Output files

File When generated Description
{Project}_{Version}_bom.json always SBOM (CycloneDX 1.6)
{Project}_{Version}_bom.spdx.json --spdx / --all, or Export as SPDX 2.3 in the UI SBOM (SPDX 2.3, converted from the CycloneDX output)
{Project}_{Version}_NOTICE.txt / .html --notice / --all / risk report default open-source notice
{Project}_{Version}_NOTICE.pdf same as above, when a PDF renderer is built into the image (--build-arg SBOM_PDF=true) the notice rendered to PDF; skipped with a log line otherwise
{Project}_{Version}_security.json / .md / .html --security / --all / risk report default Trivy security report
{Project}_{Version}_risk-report.md / .html default (all modes) — omit with --no-report open-source risk report
{Project}_{Version}_conformance.json / .md / .html every scan that generates an SBOM, also with --no-report (which skips only the risk report); --analyze produces it too, since that is what it measures format conformance report, with a regulatory crosswalk roll-up for every SBOM (EU CRA via BSI TR-03183-2, the US SBOM minimum elements of 2026 — reference only, no compliance determination). For an AI SBOM it also carries the G7 checks and, for each advisory element still missing, the CycloneDX fragment that would satisfy it. Names any best-effort post-process step that failed while the report was generated, so a pass is not read as proof every step ran cleanly; does not affect the pass/fail result or any individual check. See a rendered example
{Project}_{Version}_ai-profile.json / .md AI SBOM (--model, or --analyze on an SBOM with a model component) AI compliance profile: G7 rollup, the closable gaps with their reference links, license-flagged components, regulatory crosswalk, and the model risk assessment (riskAssessment: per-model ok/conditional/caution/review verdicts with conditions, reasons and the usage scenario; guidance, not legal advice). The same rollup opens the conformance HTML, so there is no separate HTML profile
{Project}_{Version}_scancode.json --deep-license raw scancode result
{Project}_{Version}_files.json a source-having scan (a firmware scan always; other modes when --deep-license did not already produce _scancode.json) ScanCode-shaped file-tree inventory (structure only, no licenses) backing the source-tree view
{Project}_{Version}_source.json a source-having scan snapshot of the scanned tree's file content, backing the file viewer (the scanned tree itself does not outlive the container)
{Project}_{Version}_input.json --analyze the supplier SBOM's own format, spec version, tool and authorship, captured before the CycloneDX conversion rewrites all of it
{Project}_{Version}_yocto_vex.json a Yocto build (a build directory named directly, or --analyze on one) how many CVEs the build already patched or judged not applicable — numbers not recoverable from the CycloneDX output or the security report, which list only what is still unresolved
{Project}_{Version}_vex.json web UI only, saved when a judgement (affected / not affected / fixed / under investigation, with an optional note) is recorded against a CVE on the Vulnerabilities screen the judgements recorded for this scan, keyed by component and CVE. Not produced by the CLI, and absent until the first judgement is saved for a given scan. Unlike every other file here, it is not regenerated by a scan and is not removed by re-scanning the same project and version: a judgement recorded against an earlier scan survives scanning it again
{Project}_{Version}_vex.cdx.json web UI only, built when you press Export VEX on the Vulnerabilities screen (needs at least one recorded judgement) the judgements from _vex.json as a standalone CycloneDX 1.6 VEX document that another tool can read. The four states map to CycloneDX analysis.state values (affected to exploitable, not affected to not_affected, fixed to resolved, under investigation to in_triage), and the note goes into analysis.detail. No justification is written, because the screen collects free text and CycloneDX allows only a fixed list. Each entry points at a copy of its component (name, version, PURL) held in the document itself, so the file stands alone. A judgement whose component is not in the SBOM is left out, and the screen says how many; firmware findings are the usual case, since their name and version come from the binary. It is rebuilt on every export and removed when the same project and version is scanned again, so export again afterwards
{Project}_{Version}_vex_imported.json --vex <file> on the CLI, or Import VEX on the Vulnerabilities screen in the web UI, with a CycloneDX VEX document the statements from a supplier's VEX document that apply to a component of this scan's SBOM, with the product the document describes. Kept apart from your own judgements in _vex.json: a received statement never overwrites one, and the screen labels the two separately. The four states are mapped from CycloneDX analysis.state (exploitable to affected, not_affected and false_positive to not affected, resolved and resolved_with_pedigree to fixed, in_triage to under investigation); any other state is ignored. A document whose product or version differs from the scanned SBOM's root is refused and nothing is saved. A successful import replaces this file; a refused or empty one leaves the previous file as it was. A statement that names the product itself is stored once, without a component, and applies to every finding of that CVE that has none of its own. Like _vex.json, it is not removed by re-scanning the same project and version
{Project}_{Version}_vendored.cdx.json --identify-vendored on a source scan, with the opt-in SCANOSS image vendored open-source components identified inside the source tree (SCANOSS)
{Project}_{Version}_security_epss.json whenever the security report is generated EPSS score and KEV status per vulnerability (null/false when generated offline), used to prioritize the security report
{Project}_{Version}_bom.json.sig --sign cosign signature (with --spdx, a _bom.spdx.json.sig is produced too)
{new}_model-diff.json --diff <old.json> <new.json> AI-model drift report comparing two already-generated SBOMs: matched model verdict/license/hash changes, plus any component present in only one of the two files. Named after the newer input (<new>_bom.json → <new>_model-diff.json), not {Project}_{Version} — --diff takes no project or version of its own

{P} = project name, {V} = version (special characters are normalized to _).

The conditions above are the CLI flags. In the web UI and the desktop app the same choices are the generation options on the New scan screen — Notice and Security report — and every file produced is listed in the Artifacts section of the results, downloadable per format or as one ZIP. SPDX is not a scan option there: the SBOM card in that section has an Export as SPDX 2.3 button that converts the finished BOM whenever you need it, and the converted file joins the artifact list and the ZIP. The UI has no signing, so an SPDX exported that way is unsigned; use --spdx --sign in the CLI when you need a signature. See Web UI and desktop app.

SBOM structure

bomFormat          "CycloneDX"
specVersion        "1.6"
metadata
  ├── timestamp    generation time (ISO 8601)
  └── component    project info (name, version, type)
components[]
  ├── type         "library" | "framework" | "application"
  ├── name         component name
  ├── version      version
  ├── purl         Package URL (unique identifier)
  └── licenses[]   license info (SPDX ID)
compositions[]     dependency-graph completeness (see below)

For the per-language PURL format, see Supported ecosystems.

Dependency-graph completeness

A generated SBOM carries a compositions[0].aggregate entry stating how complete its dependency graph is:

Value Meaning
complete The scan found positive evidence the graph was fully resolved: an ecosystem's lock/resolve step succeeded, or a lockfile was already committed, plus at least one dependency edge.
incomplete A known failure affected the scan: the syft fallback ran instead of cdxgen, or a firmware package-cataloging step failed.
unknown Nothing in the SBOM confirms the graph is complete. This is the default whenever there is no positive evidence either way, for example an image/rootfs/firmware/binary scan (syft alone cannot see inter-package dependencies), an AI-model, dataset or merged SBOM, or a Maven source scan (no reliable signal tells a resolved graph apart from a degraded one). unknown is not a defect; it means the tool found no basis to judge, not that something went wrong.

An analyzed supplier SBOM's own compositions declaration, if it has one, is never overwritten.

The conformance report's transitive-dependency check notes the declared value in its detail text (e.g. "12 edge(s), declared complete"), without changing the check's pass/fail status.

A preprocessing label that ran, or was satisfied by an already-committed lockfile, is recorded in the bomlens:prep-step-applied property regardless of success or failure; bomlens:pipeline-step-failed records only the failures. aggregate above is decided from both together.