How to generate an SBOM
An SBOM is produced from the final artefact (firmware image, directory, package) or from source code. The simplest route is one command in the pipeline that sends the file to Meldora after every release.
Syft (image, directory, archive)
Linux firmware (Yocto, Buildroot, OpenWrt), container images, any directory with binaries.
syft dir:./rootfs -o cyclonedx-json > sbom.cdx.json
syft dir:./rootfs-unpacked -o cyclonedx-json > sbom.cdx.json # unpack the firmware image first, e.g. with unblobAdd the product version: syft … --source-name 'Gateway GW-10' --source-version 4.2.1
cdxgen (source code)
npm, Python, Java, .NET, Go, Rust, C/C++ projects with CMake or Conan.
npx @cyclonedx/cdxgen -o sbom.cdx.json --project-name 'Kasomat Panel' --project-version 2.7.5Yocto / OpenEmbedded
Firmware built with Yocto.
# conf/local.conf
INHERIT += "create-spdx"
SPDX_INCLUDE_SOURCES = "0"
# output: tmp/deploy/spdx/… (SPDX JSON), or run Syft on the imageMeldora accepts SPDX; for CycloneDX run Syft on the rootfs image.
Zephyr RTOS
Zephyr firmware.
west spdx --init
west build -b <board>
west spdx.NET
.NET applications and services.
dotnet tool install --global CycloneDX
dotnet CycloneDX MyApp.sln -o ./sbom -jnpm / Python
Web applications and tools.
npx @cyclonedx/cyclonedx-npm --output-file sbom.cdx.json
pip install cyclonedx-bom && cyclonedx-py environment -o sbom.cdx.jsonUpload from CI
Create the API token in the settings (shown only once) and store it as a secret. The product identifier is in the sample call in the settings.
GitLab CI
sbom:
stage: release
image: alpine:3.20
script:
- apk add --no-cache curl
- curl -sSfL https://raw.githubusercontent.com/anchore/syft/main/install.sh | sh -s -- -b /usr/local/bin
- syft dir:./rootfs -o cyclonedx-json --source-version "$CI_COMMIT_TAG" > sbom.cdx.json
- curl -fsS -X POST "https://meldora.pl/api/products/$MELDORA_PRODUCT/sbom?version=$CI_COMMIT_TAG" -H "Authorization: Bearer $MELDORA_TOKEN" -F "file=@sbom.cdx.json"
rules:
- if: $CI_COMMIT_TAGGitHub Actions
- name: SBOM
uses: anchore/sbom-action@v0
with:
path: ./rootfs
format: cyclonedx-json
output-file: sbom.cdx.json
- name: Send to Meldora
run: curl -fsS -X POST "https://meldora.pl/api/products/${{ vars.MELDORA_PRODUCT }}/sbom?version=${{ github.ref_name }}" -H "Authorization: Bearer ${{ secrets.MELDORA_TOKEN }}" -F "file=@sbom.cdx.json"SBOM quality
- Every component should have a version; a component without one is not monitored.
- Make sure PURLs are present: generators add them, hand-written SBOMs usually do not.
- Put the product version in the SBOM metadata, so the file lands in the right version by itself.
- Generate the SBOM from the final artefact, not from the repository before the build: library versions often differ.
- Include statically linked dependencies (e.g. in C/C++): scanners cannot see them, but the CRA covers them.