ac6-formation, un département d'Ac6 SAS
FR
FrançaisEnglish
 
go-up

ac6 ac6-formation

SBOM pour firmware embarqué : générer, vérifier et exploiter une nomenclature logicielle

Un SBOM, ou software bill of materials, est la liste exhaustive des composants logiciels d'un produit, avec leur version et leur licence. Sur un firmware embarqué typique, cela représente entre 200 et 800 entrées, dont l'immense majorité provient de code que vous n'avez pas écrit. Le Cyber Resilience Act en fait une pièce du dossier technique, mais son intérêt réel est ailleurs : sans lui, vous ne pouvez pas répondre à la seule question qui compte quand une CVE tombe, à savoir « est-ce que ça me concerne ».

Les deux formats, et lequel choisir

SPDX (ISO/IEC 5962) vient du monde de la conformité de licences, sous l'égide de la Linux Foundation. Il est verbeux, très précis sur les licences et les relations entre paquets, et c'est le format que produisent nativement les outils de construction Linux embarqué.

CycloneDX, porté par l'OWASP, vient du monde de la sécurité applicative. Il est plus compact, orienté analyse de vulnérabilités, et gère mieux les dépendances de service et les composants matériels.

En pratique, le choix se fait rarement : vous produisez le format que votre chaîne de compilation sait générer, et vous convertissez si un client exige l'autre. Les deux sont acceptés par les autorités et les outils d'analyse savent lire les deux.

Ce qui compte davantage que le format, c'est la présence d'identifiants PURL ou CPE sur chaque composant. Sans eux, l'appariement automatique avec les bases de vulnérabilités ne fonctionne pas, et votre SBOM devient un document d'archive plutôt qu'un outil.

Générer depuis Yocto

Yocto produit un SBOM SPDX nativement, et sur les versions actuelles la classe create-spdx est héritée par défaut via INHERIT_DISTRO : il n'y a rien à activer. Sur une version plus ancienne, ou si votre distribution a modifié INHERIT_DISTRO, il faut l'ajouter explicitement :

INHERIT += "create-spdx"

Deux variables méritent d'être connues : SPDX_PRETTY pour un JSON lisible, et SPDX_INCLUDE_SOURCES pour inclure les fichiers source dans le document.

La sortie principale est un fichier IMAGE-MACHINE.spdx.json dans tmp/deploy/images/MACHINE/, accompagné de fichiers complémentaires dans tmp/deploy/spdx.

Deux points à connaître. Le SBOM décrit ce que la construction a produit, pas ce qui est réellement installé dans l'image finale : un paquet compilé mais non installé peut apparaître. Et l'archivage des sources, avec archiver, est un mécanisme distinct qu'il faut activer séparément si vous voulez pouvoir reconstruire à l'identique dans cinq ans.

Générer depuis Buildroot

Buildroot fournit make legal-info, qui produit licenses.txt, un manifeste et l'arborescence des sources. Ce n'est pas un SBOM au sens strict : pas de format normalisé, pas d'identifiants PURL, donc pas d'appariement CVE automatique.

Pour obtenir un SPDX ou un CycloneDX exploitable, il faut passer par un outil externe qui analyse le résultat, du type syft sur le système de fichiers généré :

syft dir:output/target -o spdx-json > sbom.spdx.json
syft dir:output/target -o cyclonedx-json > sbom.cdx.json

Cette approche par analyse du système de fichiers a un défaut structurel : elle voit les binaires, pas la provenance. Une bibliothèque compilée statiquement dans un exécutable disparaît de l'inventaire. C'est le point faible de toute génération a posteriori, et la raison pour laquelle un SBOM issu de la chaîne de compilation vaut mieux qu'un SBOM issu du produit fini.

Le cas Zephyr

Zephyr génère un SPDX via son outil de construction :

# dans prj.conf, ou en ligne de commande
CONFIG_BUILD_OUTPUT_META=y

west build -b <carte> <application> -d build
west spdx -d build                      # SPDX 2.3 par defaut
west spdx -d build --spdx-version 3.0   # pour SPDX 3.0

L'option --init, que l'on trouve encore dans beaucoup de tutoriels, est dépréciée et disparaîtra en Zephyr 5.0 : une construction avec CONFIG_BUILD_OUTPUT_META demande désormais elle-même les informations nécessaires.

Le résultat distingue trois documents : l'application, le SDK et le noyau Zephyr avec ses modules. Cette séparation est utile, parce que les CVE Zephyr sont publiées par module et non pour l'ensemble.

Attention au lien symbolique classique : le SBOM Zephyr couvre ce qui est compilé dans l'image, mais pas le chargeur d'amorçage. Si vous utilisez MCUboot, il faut générer et joindre son propre SBOM, sinon une vulnérabilité du chargeur passera sous le radar.

Le lien avec les CVE, là où le SBOM devient utile

Produire le document ne sert à rien sans la boucle d'exploitation. Le schéma qui fonctionne :

  1. la chaîne de compilation produit le SBOM à chaque construction, avec l'identifiant de version du firmware
  2. le SBOM est archivé, versionné, associé à la version publiée
  3. un analyseur le compare quotidiennement aux bases de vulnérabilités
  4. toute correspondance déclenche une évaluation d'applicabilité

L'étape 4 est celle qu'on oublie, et c'est la plus coûteuse. Une correspondance CVE n'est pas une vulnérabilité : le code affecté peut ne pas être compilé, la fonction peut ne pas être atteignable, la configuration peut être hors périmètre. C'est l'objet du format VEX, qui permet de déclarer formellement « ce composant est présent, cette CVE ne s'applique pas, voici pourquoi ».

Sans VEX, une équipe qui suit trois cents composants reçoit assez d'alertes non pertinentes pour cesser de les lire au bout de deux mois.

Les pièges qui rendent un SBOM inexploitable

PiègeConséquence
Généré une fois, à la mainPérimé dès la construction suivante, donc faux
Sans PURL ni CPEAucun appariement automatique possible
Produit par analyse du binaire finalLes bibliothèques statiques disparaissent
Sans version exacte, du type « 1.x »Impossible de décider si la CVE s'applique
Chargeur d'amorçage absentToute une classe de vulnérabilités invisible
Non archivé avec la version publiéeImpossible de savoir ce qu'il y avait dans le firmware de 2025

Le dernier point est le plus lourd de conséquences. L'obligation de support porte sur cinq ans minimum : vous devez pouvoir dire, en 2031, ce que contenait exactement le firmware livré en 2026. Un SBOM qui n'est pas archivé avec l'artefact ne sert à rien le jour où il servirait.

Ce qu'il faut mettre en place, dans l'ordre

Activez la génération dans la chaîne de compilation, pas à côté. Vérifiez que chaque entrée porte une version exacte et un identifiant PURL ou CPE. Archivez le SBOM avec le binaire signé, dans le même dépôt d'artefacts. Branchez un analyseur de vulnérabilités dessus. Et adoptez VEX dès la première vague d'alertes, avant que l'équipe apprenne à les ignorer.

Références

Pour aller plus loin

Ces mécanismes prennent leur sens une fois qu'on a produit un SBOM sur un vrai projet, constaté ce qui manque, et traité une première correspondance CVE de bout en bout. C'est ce que couvrent notre formation sur le Cyber Resilience Act et nos cours Linux embarqué et développement sécurisé.