Chen Embedded Software · Article · October 2026
For firmware engineers shipping STM32-based products into the EU. About 8 minutes; the commands take about 5.
Since 11 September 2026, manufacturers selling connected products in the EU must report actively exploited vulnerabilities in those products to ENISA, starting with an early warning within 24 hours. From 11 December 2027, a machine-readable software bill of materials (SBOM) becomes part of the mandatory technical documentation. Both obligations come from the Cyber Resilience Act (Regulation (EU) 2024/2847).
In practice, you can't meet a 24-hour clock unless you already know which libraries and versions are in each firmware image. That's what an SBOM is for. And for a typical STM32 project, generating one is harder than it should be.
Tools like Syft and Trivy work by reading package-manager metadata: package-lock.json, go.sum,
Debian package databases. A CubeIDE or Makefile project has none. FreeRTOS, Mbed TLS, lwIP, FatFs, the HAL drivers
and the USB library are copied into the source tree by CubeMX or by hand. Scan the folder and you typically get an
empty SBOM. Hand-write one and vulnerability scanners still miss things unless every component has exactly the right
CPE identifier.
There is a second problem: what's in the tree is not what ships. With --gc-sections,
the linker discards whole libraries you never call. An SBOM listing everything in Middlewares/ overstates
your exposure and creates false alarms.
STM32CubeIDE writes a linker map by default: after a build, look for Debug/<ProjectName>.map
(or Release/). For a Makefile or CMake build, add this to your link flags:
-Wl,-Map=build/firmware.map
The map file records every object file that contributed code or data to the final image. We'll use it to keep only components that actually ship.
fwsbom is a free, open-source (Apache-2.0) tool built for this
case. It reads the version numbers from the vendored sources themselves (for example tskKERNEL_VERSION_NUMBER
in FreeRTOS, MBEDTLS_VERSION_STRING, or the HAL's __STM32F4xx_HAL_VERSION macros) and the
STM32Cube firmware package version from your .ioc file. It then checks the map file.
pip install fwsbom
cd path/to/your/project
python -m fwsbom . --map Debug/MyProject.map --linked-only \
--name my-device --version 1.4.0 --supplier "My Company" \
--summary -o sbom.cdx.json
Example output (illustrative project):
COMPONENT VERSION LINKED EVIDENCE CMSIS-Core 5.6 ? Drivers/CMSIS/Core/Include/cmsis_version.h FreeRTOS-Kernel 10.3.1 yes Middlewares/Third_Party/FreeRTOS/Source/include/task.h STM32 USB Device Library 2.11.3 ? Middlewares/ST/STM32_USB_Device_Library/... STM32Cube FW_L4 1.18.1 ? MyProject.ioc STM32L4xx HAL Driver 1.13.4 yes Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal.c
| LINKED | Meaning |
|---|---|
yes | At least one of the component's object files is in the image |
no | Present in the tree but nothing reached the image; dropped with --linked-only |
? | Header-only, a package-level entry, or no map supplied |
The result is a CycloneDX 1.5 JSON file. Each component carries a package URL, plus a CPE where the US National Vulnerability Database has one; fwsbom's CPEs are checked against the NVD dictionary.
Feed the SBOM to Grype (on Windows: winget install Anchore.Grype):
grype sbom:sbom.cdx.json
Grype lists every matching CVE, with severity, the fixed version, an EPSS exploit-probability score, and whether the CVE is in CISA's Known Exploited Vulnerabilities catalog. That last column matters most under the CRA: an actively exploited vulnerability in your product is what triggers the 24-hour report.
As a reference point, an SBOM for a project with FreeRTOS 10.0.1, Mbed TLS 2.16.0, lwIP 2.1.2, FatFs R0.12 and cJSON 1.7.12 produces 57 matches. Old vendored libraries are where most firmware exposure hides.
A match means the version is affected, not necessarily your product. For each High or Critical finding, ask:
mbedtls_config.h, lwipopts.h and FreeRTOSConfig.h. Many CVEs affect optional features.Write the reasoning down. If a regulator or customer asks why a CVE didn't require action, that note is your answer.
An SBOM is a snapshot, but new CVEs are published against old code every week. Two habits cover it:
Need the policies and pipeline ready-made? The CRA Firmware Readiness Kit includes GitHub Actions and GitLab CI templates for exactly this pipeline, plus a vulnerability-handling policy, a disclosure policy and pre-filled ENISA 24 h / 72 h / final report templates. Prefer not to run it yourself? SBOM Watch monitors your SBOMs daily and emails you when a component becomes actively exploited.
Doesn't ST already publish an SBOM? Recent STM32Cube firmware packages include a CycloneDX
sbom_cdx.json describing the components in the package. ST notes it is a reference and does not
replace your own project SBOM. Your firmware uses a subset of the package, plus your own third-party code.
Do I need an SBOM before December 2027? The formal requirement applies from 11 Dec 2027. The reporting duty is already in force, though, and without an SBOM you can't reliably tell within 24 hours whether a newly exploited CVE affects you.
What about Zephyr or ESP-IDF? Both have their own SBOM tooling (west spdx,
esp-idf-sbom). fwsbom targets the bare-metal and RTOS projects that have none.