Software Bill of Materials
The Software Bill of Materials (SBOM) is a west extension command that can be invoked by west ncs-sbom.
It provides a list of used licenses for an application build or specific files.
Note
Generating a list of licenses from an application build is experimental. The accuracy of detection is constantly verified. Both implementation and usage may change in the future.
Overview
The process of using the ncs-sbom command involves the following steps:
Create a list of input files based on provided command-line arguments, for example, all source files used for building a specific application. For details, see Specifying input.
Detect the license applied to each file, for example, read SPDX identifier from
SPDX-License-Identifiertag. For details, see Detectors.Create an output report containing all the files and license information related to them. Depending on the selected output format, the command can also group files into packages and include package metadata in the report, for example, write a report file in HTML format. For details, see Specifying output.
When the input is a build directory, the command starts from the linked target, walks the Ninja dependency graph to collect build inputs, validates the result against the .map file, and checks archive contents with the GNU ar tool.
Requirements
The ncs-sbom command requires installation of additional Python packages.
Use the following command to install the requirements.
Enter the following command in a command-line window in the ncs folder:
pip3 install -r nrf/scripts/requirements-west-ncs-sbom.txt
Enter the following command in a terminal window in the ncs folder:
pip3 install --user -r nrf/scripts/requirements-west-ncs-sbom.txt
Enter the following command in a terminal window in the ncs folder:
pip3 install -r nrf/scripts/requirements-west-ncs-sbom.txt
Note
The scancode-toolkit detector relies on the Scancode-Toolkit, which is not part of the standard nRF Connect SDK toolchain bundle.
On Windows and Linux, the requirements-west-ncs-sbom.txt file installs ScanCode Toolkit together with its Python dependencies.
On Linux, ScanCode Toolkit requires installation of additional system dependencies. To install the required tools on Ubuntu, run:
sudo apt install python-dev bzip2 xz-utils zlib1g libxml2-dev libxslt1-dev libpopt0
On macOS with Apple Silicon installing ScanCode Toolkit with pip is not supported.
Install ScanCode Toolkit separately from a release archive and use --scancode to point to the executable if needed.
For more details, see Scancode-Toolkit Installation.
Using the command
The following examples demonstrate the basic usage of the ncs-sbom command.
The input options and output options can be combined as needed.
To see the help, run the following command:
west ncs-sbom -h
To analyze a build directory and generate the default HTML report in the build directory run:
west ncs-sbom -d build-directory
To analyze a build directory and generate an SPDX report run:
west ncs-sbom -d build-directory --output-spdx file-name.spdx
To analyze selected files and generate an HTML report run:
west ncs-sbom --input-files file1 file2 --output-html file-name.html
To analyze selected files and generate an SPDX report run:
west ncs-sbom --input-files file1 file2 --output-spdx file-name.spdx
Specifying input
You can specify all input options several times to provide more input for the report generation, for example, generate a report for two applications. You can also mix them, for example, to generate a report for the application and some directory.
To get an application SBOM from a build directory, use the following option:
-d build_directoryYou have to first build the
build_directorywith thewest buildcommand using Ninja as the underlying build tool (default). The build must be successful. Any change in the application configuration may affect the results, so always rebuild it after reconfiguration and before calling thewest ncs-sbom.You can skip this option if you are in the application directory and you have a default
builddirectory there - the same way as inwest buildcommand.The Extracting a list of files from a build directory section describes in detail how to extract a list of files from a build directory.
You can use the
-doption multiple times. For example, to include both themcubootchild image and the main application, use the following command:west ncs-sbom -d build -d build/mcuboot
Note
If the build directory is a sysbuild root (contains
domains.yaml) the command runs one analysis for each domain. It generates one output file for each requested output format and each domain. For example, with the default settings it generates one HTML report for each domain. If both HTML and SPDX outputs are requested, it generates two files for each domain. To adjust the output file names, append_<domain>before the extension (for example,sbom_report_with_mcuboot.html). To control where{domain}appears in the filename, include{domain}in--output-htmlor--output-spdx(for example,--output-spdx sbom_{domain}_sysbuild.spdx). In PS, escape the curly braces with backticks.Note
All files that are not dependencies of the
zephyr/zephyr.elftarget are not taken as an input. If you modify the.elffile after the linking, the modifications are not applied.The
-doption is experimental.Note
The build directory input expects the standard west/CMake/Ninja files including
build.ninja,CMakeCache.txtand the target.mapfile. The same flow can also be used for nRF Connect SDK Bare Metal applications if the build directory provides these files.Note
Toolchain package detection uses metadata written by the build system. The built-in runtime license mappings cover the Zephyr SDK layouts bundled with nRF Connect SDK including
arm-zephyr-eabiandriscv64-zephyr-elf.Provide a list of input files directly on the command line:
--input-files file1 file2 ...
Each argument of this option can contain globs as defined by Python’s Path.glob with two additions:
Support for absolute paths.
Exclamation mark
!to exclude files.
For example, if you want to include all
.cfiles from the current directory and all subdirectories recursively:--input-files '**/*.c'
Make sure to have correct quotes around globs, to not have the glob resolved by your shell, and go untouched to the command.
You can prefix a pattern with the exclamation mark
!to exclude some files. Patterns are evaluated from left to right, so!excludes files from patterns before it, but not after. For example, if you want to include all.cfiles from the current directory and all subdirectories recursively except allmain.cfiles, run:--input-files '**/*.c' '!**/main.c'
Read a list of input files from a file:
--input-list-file list_file
It does the same as
--input-files, but it reads files and patterns from a file (one file or pattern per line). Files and patterns contained in the list file are relative to the list file location (not the current directory). Comments starting with a#character are allowed.
Specifying output
You can specify the format of the report output using the output argument.
To generate a report in HTML format:
--output-html file-name.html
The HTML report overview section provides more details about the report.
If you use the
-doption, you do not need to specify any output argument. Thesbom_report.htmlfile is generated in your build directory (the first one if you specify more than one build directory).To generate an SPDX 2.2 format report (for CRA/EO 14028/FDA compliance):
--output-spdx file-name.spdx
The SPDX report groups files into packages and includes:
Package supplier information (auto-detected from git URLs or specified via
--package-supplier)Component name, version, and download location
Package URLs (PURLs) for unique package identification
Common Platform Enumeration (CPE) identifiers when specified via
--package-cpeDependency relationships showing supply chain connections
File checksums and license information
SPDX 2.2 is currently the supported machine-readable standardized output format.
This format meets requirements from:
Cyber Resilience Act (CRA)
U.S. Executive Order 14028
FDA cybersecurity guidelines
To generate a cache database:
--output-cache-database cache-database.json
For details, see
cache-databasedetector.
Detectors
The ncs-sbom command includes the following detectors:
spdx-tag- Search for theSPDX-License-Identifierin the source code or the binary file.For guidelines, see SPDX identifier. Enabled by default.
full-text- Compare the contents of the source file with a small database of reference texts.The database is part of the
ncs-sbomcommand. Enabled by default.scancode-toolkit- License detection by the Scancode-Toolkit. Enabled and optional by default.If the
scancodecommand is not on yourPATH, you can use the--scancodeoption to provide it, for example:--scancode ~/scancode-toolkit/scancodeThis detector is optional because it is significantly slower than the others. Due to its limitations, it is run on single files one by one using a single process.
external-file- Search for license information in an external file. Enabled by default.The external file has the following properties:
It is located in the same directory as the file under detection or in one of its parent directories .
Its name contains
LICENSE,LICENCEorCOPYING(case insensitive).It has an
SPDX-License-Identifiertag.It has one or several
NCS-SBOM-Apply-To-Filetags containing file paths or globs (as defined by the Python’s Path.glob). They are relative to the external file.
If any of the
NCS-SBOM-Apply-To-Filetags matches the file under detection, the license from the SPDX tag is used, for example:/* The following lines will apply Nordic 5-Clause license to all ".a" files * and ".lib" files in the "lib" directory and all its subdirectories. * * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause * NCS-SBOM-Apply-To-File: lib/**/*.a * NCS-SBOM-Apply-To-File: lib/**/*.lib */
This mechanism is also used for precompiled libraries including libraries in sdk-nrfxlib.
cache-database- Use license information detected and cached earlier in the cache database file. Disabled by default.Provide the cache database file using the following argument:
--input-cache-database cache-database.json
Each database entry has a path relative to the west workspace directory, a hash, and a list of detected licenses. If the file under detection has the same path and hash, the list of licenses from the database is used.
Note
To generate the database based on, for example the
scancode-toolkitdetector, run the following command:west ncs-sbom --input-files files ... --license-detectors scancode-toolkit --output-cache-database cache-database.json
git-info- Detect the source repository URL and revision for files and group files into packages. Enabled by default.The information is used in the HTML and SPDX outputs to group files into packages. If
--package-supplieris not provided the supplier is auto-detected from the repository URL.
If you prefer a non-default set of detectors, you can provide a list of comma-separated detectors with the --license-detectors option, for example:
--license-detectors spdx-tag,scancode-toolkit
Some of the detectors are optional, which means that they are not executed for a file that
already has licenses detected by some other previously executed detector.
Detectors are executed from left to right using a list provided by the --license-detectors.
--optional-license-detectors scancode-toolkit
Some detectors may run in parallel on all available CPU cores, which speeds up the detection time.
Use the -n option to limit the number of parallel threads or processes.
Compliance Options
The following options enhance SBOM compliance with CRA, EO 14028, and FDA requirements:
--package-supplier- Set the supplier/vendor name for packages:--package-supplier "Nordic Semiconductor ASA"
If not specified, the supplier is auto-detected from git repository owner/organization names.
--package-cpe- Set the Common Platform Enumeration (CPE) identifier:--package-cpe "cpe:2.3:a:nordicsemi:nrf_connect_sdk:2.0.0:*:*:*:*:*:*:*"
CPE identifiers follow the CPE 2.3 specification and help identify software packages in vulnerability databases.
These options ensure that generated SBOMs include all required fields for regulatory compliance.
HTML report overview
The HTML report has following structure:
Summary of the report, containing the following:
Notes at the beginning.
General information on the report.
List of inputs.
The file sources.
List of licenses.
All licenses detected in the input files.
List of added license texts.
If a license is not in the SPDX License List and it is in the internal database, the license text is added to the report.
You can click links in the summary to get more details about specific items.
List of files without any license information or with license information that cannot be detected automatically.
You have to investigate them manually to get the license information.
Details about each detected license:
License identifier.
Information if it is a standard SPDX license.
License name if available.
Link to license text or more details if available.
All files from the input covered by this license.
Details about each detected package:
Package name and version if available.
URL if available.
Licenses detected in files from the package.
License texts added to this report.
Extracting a list of files from a build directory
The ncs-sbom extracts a list of files from a build directory.
It queries ninja for the targets and dependencies.
The entry point is the zephyr/zephyr.elf target file.
The script asks ninja for all input targets of the zephyr/zephyr.elf target.
It also asks for all input targets of the previously extracted input targets,
until it reaches all leaves in the dependency tree.
The result is a list of all the leaves.
To change the target or specify multiple targets, you can add them after the build directory in the -d option, for example:
-d build_directory target1.elf target2.elf
There are two additional methods for improving the correctness of the above algorithm:
Each library is examined using the GNU ar tool.
If the list of files returned by the GNU ar tool is covered by the list returned from the ninja, the list is assumed to be valid. Otherwise, the library is assumed to be a leaf, so it is shown in the report and its inputs are not analyzed further.
The
ncs-sbomparses the.mapfile created during thezephyr/zephyr.elflinking.It provides a list of all object files and libraries linked to the
zephyr/zephyr.elffile. The script ends with a fatal error if any file in the.mapfile is not visible by ninja.Exceptions are the runtime and standard libraries. You can specify the list of exceptions with the
--allowed-in-map-file-onlyoption. By default, it contains common names for the runtime and standard libraries includinglibgcc.a,libc*.a,libstdc++*.a,libm*.a,crti.o,crt0.o,crtn.o,crtbegin.o, andcrtend.o.If the
.mapfile and the associated.elffile have different names, you can provide the.mapfile after the:sign following the target, for example:-d build_directory target.elf:file.map
Integration with the GN meta-build system
The ncs-sbom script reads a list of all commands needed to build provided targets.
If there is a gn gen command, the script enters the command’s build directory and tries to extract files from it using the same method as described earlier.
The results are integrated with the main build directory results.
This also applies to applications that use GN-based external projects such as Matter applications.