Skip to content

Nowcide/meta-cyclonedx

 
 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

44 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

meta-cyclonedx

⚠️ Before proceeding to read the documentation, please verify that you are on the correct branch for your Yocto release, as the feature set and default configurations may vary!

meta-cyclonedx is a Yocto meta-layer which produces CycloneDX Software Bill of Materials (aka SBOMs) from your target root filesystem.

Features

This layer generates CycloneDX compliant SBOMs with the following features:

  • Currently, support for CycloneDX specification 1.6 and 1.4
  • Support for multiple supported Yocto (LTS) releases.
  • Improved package matching against the NIST NVD by fixing CPE generation process.
  • Included purl package URLs.
  • Added generation of an additional CycloneDX VEX file which contains information on patched and ignored CVEs from within the OpenEmbedded build system.
  • Component scopes to differentiate between runtime (required) and build-time (optional) dependencies, enabling per-use-case SBOM filtering.
  • Include component licenses.
  • Added option to reduce the SBOM size by limiting SBOM collection to run-time packages (which might potentially come at some expense)

This repository was originally forked from the BG Networks repository.

Installation

To install this meta-layer simply clone the repository into the sources directory, check out the corresponding branch for your Yocto release (e.g. scarthgap, kirkstone, ...) and add it to your build/conf/bblayers.conf file:

cd sources
git clone https://github.com/iris-GmbH/meta-cyclonedx.git
cd meta-cyclonedx
git checkout <YOCTO_RELEASE>

and in your bblayers.conf file:

BBLAYERS += "${BSPDIR}/sources/meta-cyclonedx"

Configuration

To enable and configure the layer simply inherit the cyclonedx-export class in your local.conf file:

INHERIT += "cyclonedx-export"

CycloneDX Specification Version

By default, meta-cyclonedx generates CycloneDX 1.6 format SBOMs. If you need compatibility with tools that only support CycloneDX 1.4, you can configure:

CYCLONEDX_SPEC_VERSION = "1.4"

Version differences:

  • 1.4: Legacy format for compatibility with older tools
  • 1.6: Modern format with enhanced metadata and timestamps (default)

Runtime vs Build-time Packages

By default, meta-cyclonedx will only include run-time packages in the SBOM, which drastically reduces the number of potentially irrelevant packages. However, this can lead to valid packages being omitted from the SBOM (see here).

If preferred, you can add the following configuration setting (e.g in your local.conf), which will cause meta-cyclonedx to include all build-time packages as well:

CYCLONEDX_RUNTIME_PACKAGES_ONLY = "0"

Component Scopes

When including both runtime and build-time packages, meta-cyclonedx uses CycloneDX component scopes to differentiate between them:

  • Runtime packages are marked with "scope": "required"
  • Build-time only packages are marked with "scope": "optional"

This allows tools to filter components based on their use case:

  • CVE matching: Focus on components with "scope": "required"
  • License compliance: Include all components regardless of scope
  • Supply chain tracking: Include all components regardless of scope

Component scopes are enabled by default and available in both CycloneDX 1.4 and 1.6 specifications. If you need to disable them (e.g., for compatibility with certain SBOM profiles or tools):

CYCLONEDX_ADD_COMPONENT_SCOPES = "0"

Vulnerability Analysis Timestamps

By default, vulnerability analysis records include firstIssued and lastUpdated timestamps when using CycloneDX 1.6. To generate minimal VEX documents without timestamps:

CYCLONEDX_ADD_VULN_TIMESTAMPS = "0"

Component Licenses

By default, component licenses are included in the SBOM.

You may choose to exclude license information from your SBOM:

CYCLONEDX_ADD_COMPONENT_LICENSES = "0"

The licenses data is taken from the component recipe (see LICENSE. Single licenses are matched against a list of known SPDX licenses where possible.

If multiple licenses are specified using & or |, the license is converted into a SPDX license expression.

Additionally, simple expressions (only containing "AND" operators) are split into multiple license entries by default, improving the SBOM data quality. Note however, that this might not be supported by your SBOM consuming tool of choice (e.g. DependencyTrack).

To disable this feature you can set

CYCLONEDX_SPLIT_LICENSE_EXPRESSIONS = "0"

Advanced Configuration Summary

# Specification version (default: "1.6")
CYCLONEDX_SPEC_VERSION = "1.6"  # or "1.4"

# Include build-time packages (default: "1" = runtime only)
CYCLONEDX_RUNTIME_PACKAGES_ONLY = "1"

# Add component scopes (default: "1")
CYCLONEDX_ADD_COMPONENT_SCOPES = "1"

# Add vulnerability timestamps in 1.6 (default: "1")
CYCLONEDX_ADD_VULN_TIMESTAMPS = "1"

# Add component licenses (default: "1")
CYCLONEDX_ADD_COMPONENT_LICENSES = "1"

# split license expressions into multiple license entries
# when possible (default: "1")
CYCLONEDX_SPLIT_LICENSE_EXPRESSIONS = "1"

Usage

Once everything is configured simply build your image as you normally would. By default the final CycloneDX SBOMs are saved to the folder ${DEPLOY_DIR}/${PN}/cyclonedx-export as bom.json and vex.json respectively.

Uploading to DependencyTrack (tested against DT v4.11.4)

While this layer does not offer a direct integration with DependencyTrack (we consider that a feature, since it removes dependencies to external infrastructure in your build), it is perfectly possible to use the produced SBOMs within DependencyTrack.

At the time of writing DependencyTrack does not support uploading component and vulnerability information in one go (which is why we currently create a separate vex.json file). The status on supporting this may be tracked here.

Manual Upload

  1. Go into an existing project in your DependencyTrack instance or create a new one.
  2. Go to the Components tab and click Upload BOM.
  3. Select the bom.json file from your deploy directory.
  4. Wait for the vulnerability analysis to complete.
  5. Go to the Audit Vulnerabilities tab and click Apply VEX.
  6. Select the vex.json file from your deploy directory.

Automated Upload

You may want to script the upload of the SBOM files to DependencyTrack, e.g. as part of a CI job that runs after your build is complete.

This is possible by leveraging DependencyTracks REST API.

At the time of writing this can be done by leveraging the following API endpoints:

  1. /v1/bom for uploading the bom.json.
  2. /v1/event/token/{uuid} for checking the status on the bom.json processing.
  3. /v1/vex for uploading the vex.json.

Please refer to DependencyTracks REST API documentation regarding the usage of these endpoints as well as the required token permissions.

In the future we might include an example script in this repository.

Known Limitations

Potentially Missing Packages After Run-time Filtering

We use the image_list_installed_packages function from upstream OpenEmbedded as a means to reduce the SBOM contents to packages that are added to the final resulting rootfs. This drastically reduces the "noise" generated by CVEs in build-time dependencies. This however comes with some potential downsides (i.e. Missing some packages), as discussed here.

Missing Dependencies with Modern Programming Languages

OpenEmbedded and its core mechanisms work best with "traditional" programming languages such as C and C++, as these are the languages that they were initially designed around. For instance, a core-assumption prevalent in many OE mechanisms (including those we depend on in meta-cyclonedx) is that each library is described in its own OE recipe. This however does not work well with many modern programming languages, which often come with their own package managers (e.g. NPM, Cargo, Go Modules, ...), which do not necessarily integrate well into the OpenEmbedded ecosystem and depend of potentially hundreds of external dependencies (good luck writing a separate OE recipe for each dependency in a small-medium sized Node.js project).

Thus, if you rely on packages written in programming languages that come with their own package managers, you might be better off with a divide and conquer approach for covering their packages as well (your mileage may vary):

  1. Use this meta-layer to generate a CycloneDX SBOM which covers your OE-based operating system, system libraries, etc.
  2. Use tools designed explicitly for generating CycloneDX SBOMs for these languages (e.g. Rust, NPM, Golang, ...)
  3. Optionally, use some glue code to merge the SBOMs together (cyclonedx-cli offers merge functionality)

About

A Yocto meta-layer for generating CycloneDX SBOMs

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors

Languages

  • BitBake 100.0%