Aller au contenu

SBOM pour inventorier les composants réellement exécutés

SBOM pour inventorier les composants réellement exécutés

Section intitulée « SBOM pour inventorier les composants réellement exécutés »

Une SBOM (Software Bill of Materials) n’est pas une liste décorative de dépendances pour rassurer un audit. C’est un artefact de sécurité qui doit relier un binaire, une image de conteneur ou un paquet déployé à ses composants réels, à leur provenance et à leurs vulnérabilités connues.

→ Lire l’explication complète de la marmotte

SBOM : l’inventaire doit partir de l’artefact déployé

Section intitulée « SBOM : l’inventaire doit partir de l’artefact déployé »

Une SBOM recense les composants logiciels inclus dans un produit : bibliothèques, modules, paquets système, dépendances transitives, fichiers embarqués et parfois firmware. Deux formats dominent : SPDX (Software Package Data Exchange), standardisé par l’ISO (International Organization for Standardization), et CycloneDX, issu de l’écosystème OWASP (Open Worldwide Application Security Project). Les deux sont exploitables. Le choix dépend surtout des outils déjà présents dans la chaîne, pas d’une révélation mystique obtenue sur une slide de vendeur.

Le compromis central est brutal : produire la SBOM depuis le code source donne davantage de contexte sur les dépendances déclarées, mais rate les ajouts du système de construction et les fichiers introduits dans l’image finale. La produire depuis l’artefact livré reflète ce qui tourne vraiment, mais perd parfois l’intention fonctionnelle et les dépendances exclues à la compilation.

La recommandation est nette : générer une SBOM primaire depuis l’artefact immutable distribué, puis la compléter par une SBOM issue des manifestes de dépendances. Une seule de ces sources ne suffit pas. Un package-lock.json ne décrit pas une image contenant curl, OpenSSL et un certificat ajouté lors du build. À l’inverse, un scan de système de fichiers ne sait pas toujours distinguer une bibliothèque embarquée d’un fichier de test oublié dans une couche.

Le périmètre doit être défini avant de lancer les scanners :

  • une SBOM par image de conteneur, pas une SBOM générique par dépôt ;
  • une SBOM par archive publiée, paquet système ou binaire distribuable ;
  • une SBOM distincte pour les composants exécutés dans le pipeline CI/CD (Continuous Integration and Continuous Delivery) ;
  • une SBOM des dépendances d’infrastructure lorsque des modules Terraform, chart Helm ou extensions de proxy sont déployés comme du code.

Une image multi-stage contient souvent des outils de compilation absents de l’image finale. Les inclure dans la SBOM d’exécution crée du bruit et déclenche des alertes sur des composants inaccessibles en production. Les omettre de la SBOM du pipeline masque en revanche une surface d’attaque réelle : compromettre un compilateur ou un plugin de build permet de produire un artefact signé et empoisonné. L’inventaire d’exécution et l’inventaire de construction répondent à deux questions différentes.

Une SBOM ne prouve pas qu’un composant est chargé à l’exécution. Elle prouve qu’un composant a été identifié dans un artefact. Une bibliothèque présente mais jamais appelée peut rester vulnérable, notamment si une chaîne de désérialisation ou un chargement dynamique l’active plus tard. Inversement, supprimer une dépendance d’un manifeste sans reconstruire l’image ne retire absolument rien de l’image déjà publiée. Les fichiers ne lisent pas les tickets de nettoyage.

Les données minimales attendues sont : nom du composant, version exacte, fournisseur ou espace de noms, identifiant de paquet, hash cryptographique, relation de dépendance et licence. Le PURL (Package URL) identifie un paquet selon son écosystème, par exemple npm, Maven ou Alpine. Le CPE (Common Platform Enumeration) reste utile pour certains catalogues de vulnérabilités, mais son rapprochement par nom est notoirement ambigu. Un nom commun comme commons-collections ne mérite pas de décider seul d’un incident.

Vulnérabilités, VEX et limites de la corrélation

Section intitulée « Vulnérabilités, VEX et limites de la corrélation »

Une SBOM devient exploitable lorsqu’elle est corrélée aux CVE (Common Vulnerabilities and Exposures), identifiants publics de failles connues. Cette corrélation ne doit jamais produire une décision automatique de blocage à partir d’un simple nom de composant. Les faux positifs sont structurels : versions recompilées, correctifs rétroportés par une distribution, fonctionnalités non activées, code vulnérable absent du chemin d’exécution.

Le VEX (Vulnerability Exploitability eXchange) porte l’état d’exposition d’un produit face à une vulnérabilité donnée : affecté, non affecté, corrigé ou sous investigation. Ce document doit être versionné, signé et lié à l’artefact précis. Écrire « non affecté » dans un tableur détaché du livrable revient à confier une décision de sécurité à une note autocollante. Cela finit rarement bien, et jamais pendant les horaires ouvrés. Chez l’éditeur, la publication de ces déclarations revient à l’équipe de réponse aux vulnérabilités produits, quand elle existe ailleurs que sur l’organigramme.

Un statut VEX « non affecté » nécessite une justification technique vérifiable : fonction vulnérable non compilée, chemin d’appel inaccessible, correctif de distribution identifié, configuration empêchant l’exploitation. « Pas observé dans les logs » n’est pas une justification. L’absence de télémétrie prouve surtout que l’absence de télémétrie fonctionne parfaitement.

La gestion de vulnérabilités doit distinguer trois délais :

  1. Détection : délai entre la publication d’une vulnérabilité et son rapprochement avec les SBOM.
  2. Qualification : délai pour établir si l’artefact est réellement affecté.
  3. Remédiation : délai de reconstruction, test, déploiement et retrait de l’artefact vulnérable.

La SBOM réduit principalement le premier délai. Elle ne corrige pas une dépendance, ne redéploie pas une image et ne remplace pas une observabilité exploitable pour détecter un comportement anormal. Une vulnérabilité inconnue, une mauvaise configuration, un secret exposé ou un compte IAM (Identity and Access Management) trop puissant restent hors de son champ.

Les alertes doivent être enrichies par le contexte de déploiement : environnement, image par digest, exposition réseau, compte de service, droits effectifs et date de dernier démarrage. Une CVE dans une image stockée mais jamais exécutée ne se traite pas comme la même CVE dans un service exposé sur Internet avec un rôle d’administration. Le score CVSS (Common Vulnerability Scoring System) mesure des propriétés génériques de faille, pas la valeur métier de l’actif ni l’accessibilité réelle d’un port.

Exemple : générer et attester une SBOM d’image OCI

Section intitulée « Exemple : générer et attester une SBOM d’image OCI »

OCI (Open Container Initiative) définit un format d’image et de distribution de conteneurs. La SBOM doit être générée après la construction de l’image, puis attachée au digest de celle-ci. Un tag mutable tel que latest est insuffisant : il peut désigner un contenu différent quelques minutes plus tard, ce qui transforme la traçabilité en pudding quantique.

L’exemple suivant utilise Syft pour produire une SBOM CycloneDX et Cosign pour la signer. Les versions des outils doivent être épinglées dans le pipeline, vérifiées par hash et mises à jour selon une procédure suivie. Télécharger latest dans une étape de sécurité reste une manière étonnamment populaire de demander au futur de choisir ses dépendances.

Fenêtre de terminal
# Construire l'image puis récupérer son digest immuable.
docker build -t registry.example.invalid/paiement-api:1.4.2 .
DIGEST="$(docker inspect --format='{{index .RepoDigests 0}}' \
registry.example.invalid/paiement-api:1.4.2)"
# Générer la SBOM à partir de l'image finale, pas du dépôt Git.
syft "$DIGEST" \
--output cyclonedx-json=sbom-paiement-api-1.4.2.cdx.json
# Signer la SBOM avec une clé protégée hors du poste de build.
cosign sign-blob \
--key env://COSIGN_KEY \
--output-signature sbom-paiement-api-1.4.2.cdx.json.sig \
sbom-paiement-api-1.4.2.cdx.json
# Vérifier avant ingestion dans l'outil de gestion des vulnérabilités.
cosign verify-blob \
--key cosign-public.pem \
--signature sbom-paiement-api-1.4.2.cdx.json.sig \
sbom-paiement-api-1.4.2.cdx.json

La variable COSIGN_KEY ne doit pas contenir une clé privée en clair dans les variables persistantes du pipeline. Préférer une signature via OIDC (OpenID Connect) avec identité de workload, ou une clé conservée dans un HSM (Hardware Security Module). La seconde option impose une haute disponibilité du module et une procédure de reprise ; sinon, une panne du service de signature bloque les livraisons. C’est précisément le rôle d’un contrôle de sécurité : pouvoir refuser. Pas devenir un bibelot cryptographique hors de prix.

L’attestation doit contenir le digest de l’image, l’identifiant du pipeline, le commit source, la version de l’outil de génération et le hash de la SBOM. Sans ces liens, un attaquant ayant accès au registre peut remplacer l’image, conserver la SBOM et laisser l’ensemble paraître cohérent à distance. La signature lie des octets, pas des bonnes intentions.

La SBOM expose elle-même des informations : noms de composants, versions, fournisseurs, parfois chemins de fichiers et licences. Un adversaire peut l’utiliser pour accélérer la recherche de vulnérabilités. Ce risque ne justifie pas de cacher la SBOM, mais impose de séparer les artefacts publics des inventaires détaillés internes. Une SBOM destinée à un client ou à une autorité peut omettre certains chemins et métadonnées de build, sous réserve de conserver l’original signé.

Les attaques principales sont prévisibles :

  • Fausse SBOM : publication d’un document décrivant une image différente. Contre-mesure : lier et signer SBOM, image et provenance par digest.
  • Empoisonnement du build : injection d’un paquet malveillant avant la génération. Contre-mesure : dépendances verrouillées, registres privés contrôlés, isolation des runners et contrôle des identités de build.
  • Confusion de dépendance : résolution d’un paquet interne depuis un registre public. Contre-mesure : réserver les espaces de noms, configurer les sources explicitement et bloquer les résolutions implicites.
  • Dérive de runtime : modification manuelle d’un conteneur ou d’une machine après déploiement. Contre-mesure : systèmes immutables, admission contrôlée et détection de changement de fichiers.
  • Compromission de clé de signature : génération d’attestations valides pour des artefacts malveillants. Contre-mesure : clés non exportables, séparation des rôles, journalisation des signatures et révocation testée.

SLSA (Supply-chain Levels for Software Artifacts) structure les garanties de provenance du build. Son intérêt réel est de rendre vérifiables les propriétés du pipeline : source identifiée, build automatisé, provenance signée, isolement du générateur. Une SBOM sans provenance répond à « quels composants sont annoncés ? ». Une provenance sans SBOM répond à « quel build a produit cet artefact ? ». Les deux ensemble permettent enfin de poser une question qui ne soit pas purement cérémonielle.

La conservation doit suivre la durée de vie de l’artefact plus la fenêtre de réponse aux incidents. Supprimer les SBOM lors du nettoyage du registre rend impossible l’analyse d’une image restaurée depuis une sauvegarde. À l’inverse, conserver indéfiniment les clés de signature sans rotation transforme une compromission ancienne en problème contemporain.

La rotation des clés de signature exige une période de recouvrement : signer les nouveaux artefacts avec la nouvelle clé, conserver les clés publiques historiques pour vérifier les anciens, puis révoquer la clé compromise ou retirée selon une politique documentée. La sauvegarde concerne les politiques, certificats publics, journaux d’audit et métadonnées de signature. Sauvegarder une clé privée exportable sans contrôle d’accès séparé revient à créer une seconde clé privée, avec une étiquette « sauvegarde » pour rassurer le classeur.

Les événements à superviser sont précis : échec de génération de SBOM, composant sans version, différence entre SBOM source et SBOM d’image, signature absente, vérification échouée, image exécutée sans attestation, vulnérabilité nouvellement corrélée et expiration d’un certificat de signature. Cette télémétrie rejoint les principes décrits dans les pages sur les fondations d’architecture cyber et la gestion des identités. Sans inventaire des identités capables de publier, signer et déployer, la chaîne d’approvisionnement reste ouverte par la porte de service.

Sans inventaire rattaché aux artefacts livrés, la publication d’une vulnérabilité oblige à rechercher le composant manifeste par manifeste, dépôt par dépôt, alors que les bibliothèques embarquées dans un binaire ou ajoutées pendant la construction restent invisibles à cette recherche. La question « quelles images contiennent cette version ? » n’a plus de réponse vérifiable, seulement une estimation. Le tri disparaît avec elle : faute de savoir quels digests sont concernés, il ne reste que le choix entre ne rien reconstruire et tout reconstruire. Une dépendance retirée d’un manifeste continue d’être distribuée dans des images déjà publiées sans que rien ne le signale. Les demandes contractuelles ou réglementaires d’inventaire se traitent alors a posteriori, sur des artefacts parfois déjà purgés du registre, ce qui rend l’analyse d’une image restaurée impossible à documenter.

Une liste de composants logiciels est créée pour chaque programme distribué. Elle doit être fabriquée à partir du fichier réellement livré, par exemple une image utilisée pour lancer un service, car le code source ne montre pas toujours les fichiers ajoutés pendant la fabrication. Cette liste indique les noms, versions et origines des éléments trouvés.

Une base publique recense des défauts de sécurité connus. Un outil compare les composants de la liste avec cette base et signale les versions concernées. Le signalement ne suffit pas à décider : il faut vérifier si le défaut touche réellement le programme, si la fonction dangereuse est active et si un correctif existe déjà dans la version fournie.

La liste et le programme doivent être reliés par une empreinte numérique, puis signés. La signature permet de vérifier que la liste n’a pas été remplacée et qu’elle correspond bien au programme distribué. Si cette vérification échoue, le programme ne doit pas être accepté automatiquement.

Le processus peut aussi échouer si le logiciel est modifié après sa livraison, si une dépendance est téléchargée depuis une mauvaise source ou si la clé servant à signer est volée. Il faut donc limiter les droits de publication, surveiller les changements, renouveler les clés et conserver les informations nécessaires pour vérifier les anciens programmes.

À lire aussi

Pages voisines

: les deux pages se citent l’une l’autre.