SBOM Generation and CVE AnalysisΒΆ

A Software Bill of Materials (SBOM) is a structured inventory of all software components included in a shipped artefact. For embedded Linux, this includes every package, library, kernel module, and script installed in an image, along with version, dependency, and licensing metadata.

The traceability workflow is activated by a single configuration fragment: core/yocto/sbom-cve-check. This fragment is self-contained and handles the full pipeline:

  1. SPDX SBOM generation (create-spdx class): The fragment adds create-spdx to the globally inherited classes as a dependency. This class produces a full SPDX document describing every package such as its version, sources, licences, dependencies, and applied patches. See the Yocto Project SBOM documentation for the full set of options.

  2. CVE analysis (sbom-cve-check class): Takes the SPDX SBOM as input, cross-references each package against the NVD vulnerability database, and generates two output files: a CVE report (*.sbom-cve-check.yocto.json) and an enriched SPDX document (*.sbom-cve-check.spdx.json).

  3. CVE database updates: The fragment sets SRCREV = AUTOREV for the upstream CVE database recipes, so the databases are automatically fetched and kept current at the start of each build.

  4. VEX integration: The fragment sets SPDX_INCLUDE_VEX, which controls what VEX information is present in the output SPDX documents. VEX annotations are produced by sbom-cve-check itself and embedded in the outputs. Those annotations can then be forwarded into sbom-cve-review, which lets engineers inspect, sort, and supplement them. Any additional decisions made in sbom-cve-review can be exported as CVE_STATUS entries for BitBake recipes, versionable alongside the source and fed back into subsequent Yocto builds.

sbom-cve-check is available in upstream Yocto 6+ (Wrynose onwards) but must be explicitly enabled - it is not active by default. On Yocto 5 (Scarthgap), sbom-cve-check is not part of upstream Yocto at all; it is provided by the meta-sbom-cve-check layer from Bootlin. All BCA reference designs ship and configure both the class and the layer for all supported Yocto versions.

Note

In BCA reference designs the fragment is already included and configured by default for all supported Yocto versions - no manual setup is required. See Meta Layers Reference for the full list of fragments and defaults shipped with the reference design.

If you are working outside the BCA reference design, see Enabling SBOM Generation below.

Enabling SBOM GenerationΒΆ

If you are setting up a build outside the BCA reference design, add the fragment to conf/local.conf:

# Required on both Yocto 5 (needs meta-sbom-cve-check layer) and Yocto 6+ (not active by default)
OE_FRAGMENTS += "core/yocto/sbom-cve-check"

On Yocto 6+ (Wrynose and later), sbom-cve-check is part of upstream Yocto but is not active by default. The fragment must be explicitly added, as documented in the Yocto Security Manual.

On Yocto 5 (Scarthgap), sbom-cve-check is not part of upstream Yocto at all. It is provided by the meta-sbom-cve-check layer from Bootlin, which must be added to your bblayers.conf before the fragment can be enabled. The legacy cve-check class must not be used in BCA reference designs; it produces a different report format incompatible with the sbom-cve-review toolchain.

SBOM Report OutputsΒΆ

When sbom-cve-check runs after a build, it produces two files in the deploy directory:

tmp/deploy/images/<MACHINE>/
β”œβ”€β”€ <image-name>-<machine>.rootfs.sbom-cve-check.yocto.json   # CVE report for sbom-cve-review
└── <image-name>-<machine>.rootfs.sbom-cve-check.spdx.json    # Enriched SPDX for compliance
CVE report (*.sbom-cve-check.yocto.json)

Contains per-package CVE findings with status classifications. This is the primary input for sbom-cve-review. The format uses a package list where each entry carries an issue sub-list of CVE findings.

Enriched SPDX (*.sbom-cve-check.spdx.json)

The full SPDX 3.0 document enriched with CVE data. Contains substantially more metadata than the CVE report: licence texts, file lists, source download locations, patch relationships, and PURL identifiers. This is the primary compliance artefact for submission to regulators or customers.

CVE Report FormatΒΆ

The *.sbom-cve-check.yocto.json file has the following structure:

{
  "version": "1",
  "package": [
    {
      "name": "glibc",
      "layer": "core",
      "version": "2.43+git",
      "products": [
        { "product": "glibc", "cvesInRecord": "Yes" }
      ],
      "issue": [
        {
          "id": "CVE-2010-4756",
          "status": "Unpatched",
          "link": "https://nvd.nist.gov/vuln/detail/CVE-2010-4756",
          "summary": "The glob implementation in the GNU C Library allows remote authenticated users to cause a denial of service via crafted glob expressions.",
          "scorev2": "4.0",
          "scorev3": "0.0",
          "scorev4": "0.0",
          "modified": "2025-11-03T22:15:41.000",
          "vector": "NETWORK",
          "vectorString": "AV:N/AC:L/Au:S/C:N/I:N/A:P",
          "detail": "no-version-ranges",
          "description": "Check package version"
        },
        {
          "id": "CVE-2018-6551",
          "status": "Patched",
          "link": "https://nvd.nist.gov/vuln/detail/CVE-2018-6551",
          "summary": "The malloc implementation in the GNU C Library did not properly handle malloc calls with arguments close to SIZE_MAX.",
          "scorev2": "7.5",
          "scorev3": "9.8",
          "scorev4": "0.0",
          "modified": "2024-11-21T04:10:53.000",
          "vector": "NETWORK",
          "vectorString": "CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H",
          "detail": "version-not-in-range"
        },
        {
          "id": "CVE-2019-1010022",
          "status": "Ignored",
          "link": "https://nvd.nist.gov/vuln/detail/CVE-2019-1010022",
          "summary": "GNU Libc is affected by a mitigation bypass allowing an attacker to bypass stack guard protection.",
          "scorev2": "7.5",
          "scorev3": "9.8",
          "scorev4": "0.0",
          "modified": "2024-11-21T04:17:55.000",
          "vector": "NETWORK",
          "vectorString": "CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H",
          "description": "Upstream glibc maintainers dispute there is any issue and have no plans to address it further."
        }
      ],
      "cpes": ["cpe:2.3:*:*:glibc:2.43:*:*:*:*:*:*:*"]
    }
  ]
}

Key fields in each issue entry:

  • id: CVE identifier (e.g. CVE-2018-6551)

  • status: Patched, Unpatched, or Ignored

  • scorev2, scorev3, scorev4: CVSS score strings for each version

  • vector: Attack vector category (e.g. NETWORK, LOCAL)

  • vectorString: Full CVSS vector string

  • detail: Machine-readable reason code (e.g. version-in-range, version-not-in-range, no-version-ranges, not-applicable-config)

  • description: Human-readable explanation (typically present when status is Ignored)

  • modified: Timestamp of the last NVD modification

Verifying SBOM GenerationΒΆ

After a build, verify both output files were generated:

ls -lh tmp/deploy/images/*/*.sbom-cve-check.yocto.json
ls -lh tmp/deploy/images/*/*.sbom-cve-check.spdx.json

Fixing Vulnerabilities in RecipesΒΆ

There are two ways to change the status of a CVE in the report:

1. Apply a patch: include the CVE identifier in a CVE: tag in the patch file’s commit message. sbom-cve-check reads this tag and automatically marks the CVE as Patched:

From: Security Team <security@accelerat.eu>
Subject: [PATCH] avformat/nutdec: Add check for avformat_new_stream

Check for failure of avformat_new_stream() and propagate the error code.

CVE: CVE-2022-3341
Upstream-Status: Backport [https://github.com/FFmpeg/FFmpeg/commit/9cf652c]
Signed-off-by: Engineer Name <engineer@accelerat.eu>
---
# In the recipe:
SRC_URI += "file://0001-CVE-2022-3341-fix-nutdec.patch"

2. Annotate with CVE_STATUS: when a CVE does not require a patch (e.g. the affected feature is disabled or the issue is not applicable to your configuration), set the CVE_STATUS variable flag in the recipe or a .bbappend:

   CVE_STATUS[CVE-2016-10642] = "cpe-incorrect: This is specific to the npm package \
       that installs cmake, so isn't relevant to OpenEmbedded"

The reason string before the colon maps to ``Ignored`` in the report. See the `Yocto Security Manual (fixing vulnerabilities) <https://docs.yoctoproject.org/dev/security-manual/vulnerabilities.html#fixing-vulnerabilities-in-recipes>`_ for the full list of accepted reason codes.

Annotation can also be applied via the sbom-cve-review UI, which generates the correct CVE_STATUS entries and exports them as .bbappend files. See VEX Decisions and Compliance Export for the full workflow.

Storing and Archiving SBOMsΒΆ

For compliance and audit trails, store SBOM reports alongside release artefacts:

# Suggested directory structure
releases/v1.0.0/
β”œβ”€β”€ bunker-os-image-qemuarm64.wic.gz
β”œβ”€β”€ bunker-os-image-qemuarm64.rootfs.sbom-cve-check.yocto.json
β”œβ”€β”€ bunker-os-image-qemuarm64.rootfs.sbom-cve-check.spdx.json
β”œβ”€β”€ open-world-image-qemuarm64.rootfs.tar.gz
β”œβ”€β”€ open-world-image-qemuarm64.rootfs.sbom-cve-check.yocto.json
β”œβ”€β”€ open-world-image-qemuarm64.rootfs.sbom-cve-check.spdx.json
└── MANIFEST.md  # Release notes and build metadata

Include a manifest documenting the build date, Yocto version, and which meta-layers were used:

# Release v1.0.0

**Build Date:** 2026-05-21T10:30:00Z
**Yocto Version:** 6.0 (Wrynose)
**Machine:** qemuarm64

## Meta-Layers
- poky: commit abc123def456
- meta-openembedded: commit def456ghi789
- meta-bsp-custom: commit ghi789jkl012

## Images
- bunker-os-image CVE report: bunker-os-image-qemuarm64.rootfs.sbom-cve-check.yocto.json
- bunker-os-image SPDX: bunker-os-image-qemuarm64.rootfs.sbom-cve-check.spdx.json
- open-world-image CVE report: open-world-image-qemuarm64.rootfs.sbom-cve-check.yocto.json
- open-world-image SPDX: open-world-image-qemuarm64.rootfs.sbom-cve-check.spdx.json

Next StepsΒΆ

Once SBOM and CVE reports are generated and vulnerabilities are addressed, proceed to VEX Decisions and Compliance Export to record engineering decisions, export CVE_STATUS entries back into recipes, and assemble a compliance-ready SBOM + CVE + VEX bundle.