Aller au contenu principal
own2pwn
appsec/sbom-software-bill-of-materials.tsx

SBOM (Software Bill of Materials) : l'inventaire qui manque à votre supply chain

SBOM (Software Bill of Materials) : l'inventaire lisible par machine de tous les composants d'un logiciel. Formats, génération, cadre réglementaire et limites.

own2pwn··12 min de lecture

Décembre 2021, un vendredi soir. La CVE Log4Shell vient de tomber, note maximale, exploitable en une ligne, et déjà scannée en masse sur tout l'internet. Dans la war room improvisée, quelqu'un pose la seule question qui compte : "on utilise Log4j où, déjà ?". Silence. Personne ne sait répondre vite. Log4j n'est presque jamais une dépendance qu'on installe soi-même : elle arrive en passager clandestin, tirée par un framework, lui-même tiré par un autre. Il a fallu des jours de grep, de builds relancés et de coups de fil aux éditeurs pour établir une liste que personne n'avait sous la main. Cette liste, justement, porte un nom : un SBOM.

Un SBOM (Software Bill of Materials, ou nomenclature logicielle) est l'inventaire, lisible par une machine, de tous les composants qui entrent dans un logiciel : chaque dépendance, sa version, souvent sa licence et son origine. L'idée n'a rien de révolutionnaire, c'est la même que la nomenclature d'une voiture ou d'un médicament : la liste exacte de ce qu'il y a dans la boîte. Sauf qu'en informatique, cette boîte contient des centaines de pièces qu'aucun humain n'a choisies une par une. Reste à savoir ce que le SBOM, c'est quoi au juste, ce qu'il permet le jour d'un incident, et pourquoi il ne vaut rien tant qu'il dort dans un tiroir.

Le SBOM, c'est quoi exactement ?

Le code moderne n'est plus vraiment écrit, il est assemblé. Un projet web anodin déclare une poignée de dépendances directes, qui en tirent chacune d'autres, sur cinq ou six niveaux de profondeur. Résultat : un node_modules de plusieurs centaines de paquets pour une application dont vous n'avez lu qu'un pour cent du code réellement exécuté. Le software bill of materials met tout ça à plat. Là où votre package.json ne liste que ce que vous avez demandé explicitement, le SBOM énumère l'arbre complet, transitives comprises, avec les versions figées qui tournent vraiment.

arbre-vers-sbom
VOUS
package.json
Trois ou quatre dépendances directes, celles que vous avez écrites à la main.
RÉSOLUTION
Arbre transitif
Des centaines de nœuds sur plusieurs niveaux, verrouillés par le lockfile.
SBOM
Nomenclature lisible par machine
Chaque composant, sa version exacte, sa licence, son origine. Une liste interrogeable en une requête.
Vous choisissez une poignée de dépendances directes. Le SBOM aplatit tout l'arbre, y compris les niveaux que vous n'avez jamais choisis.

La nuance qui change tout, c'est "lisible par machine". Un SBOM n'est pas un document Word que quelqu'un tient à jour à la main ; c'est un fichier structuré (JSON ou XML) qu'on génère automatiquement à partir du build et qu'on interroge par programme. Quand la prochaine faille type Log4Shell tombe, vous ne relancez pas des heures de grep : vous filtrez votre SBOM sur le nom du composant, et vous savez en quelques secondes quels produits et quelles versions sont concernés. C'est exactement la réponse que personne n'avait ce fameux vendredi de décembre.

Les formats : CycloneDX et SPDX

Pour qu'un outil génère un SBOM qu'un autre outil sait relire, il faut une grammaire commune. Deux formats standards se partagent le terrain, et ils coexistent très bien :

  • CycloneDX, porté par l'OWASP, est né côté sécurité applicative. Il est compact, orienté analyse de risque, et gère nativement les dépendances, les vulnérabilités connues, les signatures et même les modèles de machine learning. C'est souvent le choix par défaut quand l'objectif est de corréler l'inventaire à des CVE.
  • SPDX, standardisé par la Linux Foundation puis devenu norme ISO/IEC 5962, vient historiquement du monde de la conformité des licences open source. Il est plus verbeux, très rigoureux sur la traçabilité juridique, et fréquent dans les contextes réglementaires et les grandes chaînes d'approvisionnement.

En pratique, le débat CycloneDX contre SPDX importe moins qu'on ne le croit : les bons outils exportent dans les deux, et des convertisseurs font le pont. Ce qui compte, c'est que le format soit standard et interopérable, pas qu'il soit l'un plutôt que l'autre. Voici à quoi ressemble un extrait CycloneDX, réduit à un seul composant pour la lisibilité :

json
{
  "bomFormat": "CycloneDX",
  "specVersion": "1.6",
  "serialNumber": "urn:uuid:3e671687-1c5d-4a2f-9b0e-1f2c8a4d5e6f",
  "version": 1,
  "components": [
    {
      "type": "library",
      "name": "log4j-core",
      "group": "org.apache.logging.log4j",
      "version": "2.14.1",
      "purl": "pkg:maven/org.apache.logging.log4j/log4j-core@2.14.1",
      "licenses": [
        { "license": { "id": "Apache-2.0" } }
      ]
    }
  ]
}

Le champ vraiment central, c'est le purl (package URL) : un identifiant normalisé qui décrit sans ambiguïté d'où vient le paquet (écosystème, nom, version). C'est la clé qui permet de confronter votre inventaire aux bases de vulnérabilités : un purl d'un côté, une CVE indexée sur le même purl de l'autre, et la correspondance se fait toute seule.

À quoi sert un SBOM, concrètement

Un inventaire, sur le papier, ça n'impressionne personne. Ce qui compte, ce sont les questions auxquelles il permet de répondre vite, et qui, sans lui, tournent au cauchemar. Trois usages reviennent tout le temps.

Répondre en minutes à "suis-je affecté par la CVE X ?"

C'est l'usage roi, celui qui justifie à lui seul l'effort. Une faille critique est publiée sur un composant très répandu. Sans SBOM, chaque équipe part en fouille manuelle, projet par projet, et l'incertitude dure des jours. Avec un SBOM tenu à jour, c'est une requête : quels artefacts embarquent ce purl, dans quelle version, sur quel périmètre. La différence entre une réponse en dix minutes et une réponse en deux semaines, c'est la différence entre un incident maîtrisé et une fenêtre d'exposition grande ouverte pendant que les scanners d'attaquants passent.

Gérer les licences

L'autre moitié de l'histoire est juridique. Chaque dépendance vient avec une licence, et toutes ne se marient pas. Une bibliothèque en GPL qui se glisse dans un produit propriétaire distribué, et c'est un problème de conformité qui peut coûter cher. Le SBOM matérialise cet inventaire des licences, ce qui permet de détecter tôt une incompatibilité plutôt que de la découvrir lors d'une due diligence de rachat ou d'un contrôle.

Prouver la conformité

Enfin, le SBOM est de plus en plus une pièce contractuelle et réglementaire. Un client grand compte ou une administration exige de plus en plus souvent la nomenclature du logiciel qu'il achète, comme il exigerait la composition d'un produit physique. Fournir un SBOM propre devient un argument commercial autant qu'une case à cocher, et son absence, un motif de disqualification.

Comment on génère un SBOM

Bonne nouvelle : on ne rédige jamais un SBOM à la main. On le dérive automatiquement, soit depuis les manifestes et lockfiles d'un projet, soit en inspectant un artefact déjà construit (un binaire, une image conteneur). Le premier réflexe, pour un projet Node, tient dans une commande native :

bash
# Node : lister l'arbre complet, versions résolues comprises
npm ls --all --json > dependencies.json

# Générer un vrai SBOM CycloneDX depuis le lockfile
npx @cyclonedx/cyclonedx-npm --output-file sbom.cdx.json

L'approche par manifeste a une limite : elle ne voit que ce qui est déclaré. Pour inventorier ce qui se trouve vraiment dans une image conteneur ou un binaire livré, y compris les paquets système et les dépendances embarquées sans manifeste, on scanne l'artefact final. L'outil de référence, open source, est syft (de la même famille que le scanner de vulnérabilités Grype) :

bash
# SBOM d'une image conteneur, au format CycloneDX
syft my-app:latest -o cyclonedx-json=sbom.cdx.json

# ... ou au format SPDX, selon ce que le destinataire attend
syft my-app:latest -o spdx-json=sbom.spdx.json

# Scanner un répertoire de code source plutôt qu'une image
syft dir:. -o cyclonedx-json

Le bon moment pour générer un SBOM, c'est à chaque build, dans la CI/CD, en même temps que l'artefact qu'il décrit. Un SBOM produit après coup, sur un poste de développeur, risque de ne pas correspondre exactement à ce qui part en production. Généré par le pipeline et archivé aux côtés de l'image, il devient une photographie fidèle et datée de chaque version livrée. La plupart des outils de SCA (analyse de composition logicielle) intègrent d'ailleurs cette étape : ils produisent le SBOM et enchaînent directement sur la corrélation aux vulnérabilités connues, ce sur quoi on revient plus bas.

Le cadre réglementaire qui pousse le SBOM

Si le SBOM est passé en quelques années d'une curiosité d'ingénieur à une exigence de direction, c'est en grande partie sous la pression du droit. Deux moteurs, un de chaque côté de l'Atlantique.

Aux États-Unis, le décret présidentiel Executive Order 14028 de mai 2021, pris dans la foulée de l'affaire SolarWinds, a fait du SBOM une exigence pour tout éditeur vendant du logiciel au gouvernement fédéral. C'est ce texte qui a vraiment lancé la dynamique : du jour au lendemain, fournir une nomenclature logicielle est devenu une condition d'accès à un marché énorme, et les outils ont suivi.

En Europe, le levier est le Cyber Resilience Act. Le règlement inscrit noir sur blanc, dans ses exigences essentielles, l'obligation pour le fabricant d'établir et de tenir à jour un SBOM couvrant tous les composants du produit, dépendances open source comprises. Le SBOM y est explicitement présenté comme le prérequis du signalement rapide des vulnérabilités exploitées : on ne tient pas un délai de vingt-quatre heures sans savoir instantanément ce que l'on embarque. On détaille ce texte, ses échéances et ses sanctions dans notre article dédié au Cyber Resilience Act.

Le SBOM n'est pas qu'une case de conformité
Il est tentant de réduire le SBOM à une obligation à cocher pour satisfaire un auditeur. C'est passer à côté de l'essentiel. La réglementation ne fait qu'imposer une hygiène qui a une vraie valeur défensive : un SBOM sert d'abord vos équipes le jour d'un incident, bien avant de servir un contrôle. Le traiter comme un livrable mort, c'est se priver de son seul intérêt.

Les limites : un SBOM ne vaut que tenu à jour et corrélé

Voilà où beaucoup d'équipes se trompent. Générer un SBOM une fois, l'archiver fièrement, et considérer le sujet clos, c'est fabriquer un document mort. Un SBOM n'a de valeur que branché sur deux choses.

sbom-vivant
Socle
SBOM : l'inventaire brut
La liste des composants et versions à un instant T. Nécessaire, mais inerte tout seul.
Couche 1
Fraîcheur : régénéré à chaque build
Sinon il décrit une version qui n'est plus en production.
Couche 2
Corrélation aux CVE (la SCA)
Confronté en continu aux bases de vulnérabilités. C'est là que l'inventaire devient une alerte.
Un SBOM seul n'est qu'une liste figée. Sa valeur naît des deux couches qu'on empile par-dessus : la fraîcheur et la corrélation aux vulnérabilités.

La fraîcheur d'abord. Un SBOM décrit un état à un instant précis. Vos dépendances bougent à chaque mise à jour, chaque déploiement. Un inventaire daté du mois dernier peut vous rassurer à tort sur une version qui n'est plus celle qui tourne. D'où la règle : régénérer le SBOM à chaque build, jamais une fois pour toutes.

La corrélation ensuite. Un SBOM ne dit pas si un composant est vulnérable, il dit seulement qu'il est là. Pour qu'il déclenche une action, il faut le confronter en permanence aux bases de vulnérabilités publiées : c'est exactement le rôle de la SCA, qu'on va relier au sujet. Un SBOM sans corrélation, c'est un carnet d'adresses sans téléphone : complet, à jour, et parfaitement inutile au moment où ça compte.

Ce qu'un SBOM ne voit pas non plus
Même vivant, un SBOM inventorie ce que vous déclarez et compilez. Il ne voit pas le <script> tiers chargé dynamiquement dans le navigateur de vos visiteurs, ni le CDN qui change de propriétaire après votre déploiement. Le drame polyfill.io est, par construction, hors de portée d'un SBOM classique. C'est le genre d'angle mort que seule une vue depuis la surface externe vient combler, et qu'on détaille dans le pilier sur les attaques supply chain.

SBOM, SCA et sécurité de la supply chain

Il reste à replacer le SBOM dans son écosystème, parce qu'on le confond souvent avec ses voisins. Le lien le plus direct est celui avec la SCA (Software Composition Analysis, analyse de composition logicielle). La distinction est simple : le SBOM est l'inventaire, la SCA est l'analyse de cet inventaire. La SCA prend le SBOM, le confronte aux bases de CVE, applique éventuellement une politique (bloquer un build qui embarque une faille critique, alerter sur une licence interdite), et transforme la liste passive en signal actionnable. Sans SBOM, la SCA n'a rien à analyser ; sans SCA, le SBOM ne produit aucune alerte. On les met donc en place ensemble, dans cet ordre.

Cette corrélation continue est aussi la brique de base d'une vraie gestion des vulnérabilités : on ne priorise et on ne remédie que ce qu'on a d'abord inventorié. Un programme de gestion des vulnérabilités qui ignore ses dépendances tierces regarde à côté de la porte par où entre aujourd'hui l'essentiel des compromissions.

Reste le pan que le SBOM et la SCA ne couvrent pas : ce qui se charge dans le navigateur de vos visiteurs, à l'exécution, hors de tout manifeste. Un script de CDN, un tag analytics, un widget racheté par un acteur hostile ne figurent nulle part dans votre package.json. Pour les voir, il faut adopter le point de vue de l'attaquant et regarder la surface exposée depuis l'extérieur, en continu. C'est précisément ce que fait notre module de sécurité de la chaîne d'approvisionnement, complémentaire du SBOM plutôt que concurrent : l'un regarde ce que vous compilez, l'autre ce que vous servez réellement.

À retenir

  • Un SBOM (software bill of materials) est l'inventaire lisible par machine de tous les composants d'un logiciel : dépendances, versions, licences, origine, transitives comprises.
  • Deux formats standards et interopérables : CycloneDX (OWASP, orienté sécurité) et SPDX (Linux Foundation, orienté licences et conformité). Le champ purl est la clé de corrélation aux CVE.
  • Son usage roi : répondre en minutes, et non en semaines, à "suis-je affecté par la CVE X ?", comme le jour de Log4Shell. Plus la gestion des licences et la preuve de conformité.
  • On le génère automatiquement (npm ls, syft, outils de SCA), à chaque build, dans la CI/CD.
  • Le Cyber Resilience Act européen et l'executive order américain en font une obligation d'accès au marché.
  • Un SBOM ne vaut que tenu à jour et corrélé aux vulnérabilités : c'est le rôle de la SCA. Et il reste aveugle au code tiers chargé dans le navigateur, que seule une vue depuis la surface externe capte.

Un SBOM propre vous dit de quoi vos produits sont faits. Il ne vous dit pas ce que vos pages chargent réellement chez vos visiteurs, ni quels composants tiers de votre surface exposée sont déjà vulnérables. C'est là que notre module de sécurité de la chaîne d'approvisionnement prend le relais, en continu et depuis l'extérieur. Envie d'en parler avec un humain qui manipule ces sujets au quotidien ? La page contact vous met en lien direct avec un pentester.

Articles liés