Construire un SBOM conforme à la CISA 2026 à la main : tout ce que vous faites sans monsys
Les Minimum Elements 2026 ont transformé un SBOM en un artefact signé, licencié et vérifiable par machine. Voici la chaîne manuelle complète pour un hôte Linux : inventorier trois couches, remplir chaque champ requis, canoniser et signer en Ed25519, puis dériver le VEX. C'est beaucoup.
Notre article précédent expliquait ce qu'exigent les Minimum Elements 2026 de la CISA. Voici la suite honnête : si vous n'avez pas monsys, voilà ce qu'il faut réellement pour produire à la main un SBOM conforme pour une seule machine. Faites-le une fois et vous comprendrez pourquoi « générez juste un SBOM » n'est pas une case à cocher.
Nous en construisons un pour un hôte Linux. Windows a une forme semblable, mais un outillage différent.
Étape 1 : inventorier trois couches, pas une
Une machine n'est pas seulement ses dépendances applicatives. Un SBOM d'hôte conforme couvre tout ce qui peut porter une CVE :
- Dépendances applicatives (lockfiles)
- Paquets OS (la base de paquets de la distribution)
- Le noyau en cours d'exécution
Dépendances applicatives
Parcourez le lockfile de chaque écosystème : package-lock.json, requirements.txt, composer.lock, go.sum, et ainsi de suite. Des outils comme Syft aident ici, mais fusionner les résultats en un seul document et réconcilier les versions reste votre travail.
Paquets OS
Interrogez le gestionnaire de paquets, une syntaxe par famille de distribution.
Debian / Ubuntu :
dpkg-query -W -f='${Package}\t${Version}\t${Architecture}\n'
RPM (RHEL / Fedora / Rocky / Alma) :
rpm -qa --qf '%{NAME}\t%{VERSION}-%{RELEASE}\t%{ARCH}\t%{LICENSE}\n'
Alpine :
apk info -v
Transformez maintenant chaque ligne en Package URL. openssl 3.0.13 sur Ubuntu 22.04 devient :
pkg:deb/ubuntu/openssl@3.0.13?arch=amd64&distro=ubuntu-22.04
Trompez-vous de qualifieurs et la correspondance CVE en aval échoue silencieusement.
Le noyau en cours d'exécution
uname -r # 6.8.0-100-generic
uname -m # x86_64
Ce qui devient pkg:deb/ubuntu/linux-kernel@6.8.0-100-generic?arch=x86_64&distro=ubuntu. Marquez-le ensuite comme composant operating-system (CycloneDX type, SPDX primaryPackagePurpose), sinon un scanner traite votre noyau comme une bibliothèque npm.
Étape 2 : remplir chaque champ 2026 requis
La norme n'est pas « une liste de noms ». Par composant, vous devez désormais :
- Component Producer. Associez chaque distribution à un vrai producteur : Ubuntu à Canonical Ltd., Debian au Debian Project, Alpine à Alpine Linux, et ainsi de suite. Là où vous ne pouvez vraiment pas trancher, vous devez écrire
NOASSERTION, pas deviner. - Component Identifiers. Au moins un purl ou CPE, comme ci-dessus.
- Component License. Un identifiant de licence SPDX. Sur Debian, cela signifie parcourir
/usr/share/doc/<pkg>/copyright, qui est du texte libre, et le mapper vers un ID SPDX. Sur RPM vous obtenez%{LICENSE}, plus proche mais pas toujours une expression SPDX valide. - Component Hash + Algorithm. Une empreinte de l'artefact, avec un nom d'algorithme enregistré à l'IANA. Voici le piège : un inventaire de métadonnées n'a pas les octets originaux de l'artefact. Soit vous téléchargez et hachez chaque artefact, soit vous enregistrez l'empreinte comme réellement inconnue. En fabriquer une est pire que de n'en fournir aucune, et l'élément « Explicitly Identifying Unknown Information » de la norme exige que vous le disiez honnêtement.
Puis les métadonnées au niveau du document : Author, Author Signature (Étape 3), Data Format Name et Version, Timestamp (RFC 9557 / RFC 3339), Tool Name et Version, Generation Context (avant / pendant / après build), et une SBOM Version en versionnage sémantique.
Étape 3 : le signer pour que chacun puisse vérifier
C'est la partie que la plupart des SBOM artisanaux sautent, et elle est désormais obligatoire.
- Générez une clé :
openssl genpkey -algorithm ed25519 -out sbom-key.pem
- Canonisez le document avec RFC 8785 (JSON Canonicalization Scheme), en retirant le porteur de signature. Il n'existe pas d'option
opensslpour cela. JCS trie les clés d'objet par code unit UTF-16, utilise un échappement minimal et un format de nombre spécifique. Vous écrivez ou importez une bibliothèque JCS, et si vous signez les mauvais octets, chaque vérificateur en aval rejette la signature. - Signez les octets canoniques avec la clé Ed25519.
- Intégrez la signature. CycloneDX a un bloc
signatureJSF natif ; SPDX n'a pas de champ de signature, vous la portez donc dans une annotation au niveau du document. - Publiez la clé publique à un endroit récupérable, pour qu'un tiers puisse re-canoniser le fichier, récupérer votre clé et la vérifier hors ligne.
Ratez l'une de ces cinq étapes et vous avez une signature que personne d'autre ne peut vérifier, ce qui équivaut à aucune signature.
Étape 4 : dériver le VEX, car une liste n'est pas l'objectif
La norme de 2026 ajoute une section sur la corrélation des SBOM avec les avis de sécurité, en nommant explicitement VEX et CSAF. L'inventaire n'est donc que la moitié du livrable. Pour chaque composant, vous devez maintenant :
- Le rapprocher d'une source de vulnérabilités. OSV.dev prend des triplets
(écosystème, nom, version)groupés ; NVD correspond par CPE. - Décider d'un statut par CVE :
affected,not_affected,fixedouunder_investigation. - Le justifier. OpenVEX exige un
action_statementpouraffectedet une justification ou unimpact_statementpournot_affected. Un correctif noyau backporté se lit comme « fixed » même si la version paraît encore vulnérable ; il vous faut donc une conscience des backports de la distribution, ou vous sur-rapportez. - Émettre du OpenVEX ou du CycloneDX-VEX.
Trompez-vous dans le sens prudent et vous inondez votre auditeur de faux positifs. Trompez-vous dans le sens commode et vous masquez silencieusement une exposition réelle.
Étape 5 : maintenant, faites-le pour toujours, sur chaque hôte
Les étapes ci-dessus produisent un SBOM pour une machine à un instant donné. La norme demande aussi Frequency (régénérer à chaque changement) et Distribution and Delivery (le proposer via une API ou une URL). Vous enveloppez donc toute la chaîne dans un ordonnanceur, stockez les sorties, exposez un endpoint, faites tourner et protégez la clé de signature, et recommencez pour chaque hôte de la flotte. Chaque nouvelle distribution est une nouvelle table de producteurs et une nouvelle bizarrerie d'analyse de licences.
Le décompte honnête
Pour un seul hôte Linux, conforme et signé, à la main :
- 3 sources d'inventaire, fusionnées et dédupliquées
- construction de purl avec les bons qualifieurs de distribution
- une correspondance distribution-vers-producteur
- une correspondance texte-de-licence-vers-ID-SPDX
- une politique honnête d'empreinte inconnue
- 9 champs de métadonnées du document
- une clé Ed25519, un canoniseur JCS et un chemin d'intégration-et-publication
- une dérivation VEX avec justification par CVE et conscience des backports
- un ordonnanceur, du stockage et un endpoint de livraison
C'est un petit projet, pas une commande.
Ou : la version monsys
monsys fait tout ce qui précède à partir de données que l'agent rapporte déjà. Ouvrez un hôte, allez dans l'onglet CVE, et la barre d'export d'audit vous donne le SBOM (SPDX 2.3 ou CycloneDX 1.5) et le VEX (OpenVEX ou CycloneDX-VEX), chacun signé avec notre clé Ed25519 et vérifiable hors ligne avec notre clé publique publiée. Ou récupérez-les directement depuis l'API :
GET /api/v1/agents/{id}/sbom?format=spdx-json
GET /api/v1/agents/{id}/sbom?format=cyclonedx-json
GET /api/v1/agents/{id}/vex?format=openvex
Les mêmes données, la même signature, regroupées dans l'Audit Pack mensuel. Tout est généré à l'intérieur d'une plateforme hébergée dans l'UE, sans rien envoyer à des tiers.
Contexte : La CISA a réécrit les règles du SBOM. Détail technique : docs.monsys.ai/fr/security/sbom-vex. Cinq premiers serveurs gratuits : monsys.ai/fr/signup.