SBOM
Ce que ratent les générateurs de SBOM open source
Syft, Trivy et cdxgen sont performants, gratuits et largement utilisés. Tous trois construisent une SBOM à partir des fichiers que vous leur indiquez : lockfiles, manifestes ou paquets installés. C'est pourquoi ils divergent sur un même dépôt, et pourquoi aucun d'eux ne voit ce que le build a récupéré en dehors de ces fichiers.
Mis à jour le
Comment générer une SBOM avec chaque outil
Pour chaque outil, une seule commande suffit pour un répertoire source ou une image de conteneur, avec une sortie CycloneDX ou SPDX :
# Syft: a source directory or a container image
syft ./my-project -o cyclonedx-json=sbom.cdx.json
syft my-image:latest -o spdx-json=sbom.spdx.json
# Trivy: a filesystem or a container image
trivy fs --format cyclonedx --output sbom.cdx.json .
trivy image --format spdx-json --output sbom.spdx.json my-image:latest
# cdxgen: the current directory, optionally with a project type
cdxgen -o bom.json .
cdxgen -t js -o bom.json . Les commandes sont la partie facile. Ce qui se retrouve dans le fichier dépend de ce que lit chaque outil, et ils ne lisent pas les mêmes choses.
Ce que lit chaque outil
| Outil | Répertoire source | Image de conteneur | Bon à savoir |
|---|---|---|---|
| Syft | Un ensemble de catalogers par défaut pour les répertoires, qui lit les dépendances déclarées | Un ensemble de catalogers par défaut pour les images, qui lit les paquets installés | Les catalogers sont choisis selon le type de scan. syft cataloger list montre ceux qui s'exécutent, et --select-catalogers en ajoute ou en retire. |
| Trivy | Les lockfiles ; pour Node.js, package-lock.json, yarn.lock, pnpm-lock.yaml et bun.lock |
Pour Node.js, les fichiers package.json sous node_modules |
Exclut les dépendances de développement, sauf si vous passez --include-dev-deps. |
| cdxgen | Les lockfiles d'abord, qui incluent les dépendances de développement ; pour Node.js, il analyse aussi les imports dans le code | Pris en charge | Définissez le type de projet avec -t pour limiter ce qu'il recherche. |
Pourquoi ils divergent sur un même dépôt
Pointez les trois vers un même commit et vous obtenez trois listes différentes. Aucun n'est défaillant. Chacun suit ses propres règles documentées :
- Pas de lockfile, pas de dépendances. Express 5.2.1 ne commite aucun lockfile. Sur un checkout propre, un outil qui résout les dépendances à partir des lockfiles ou des paquets installés n'a ni les uns ni les autres : les dépendances npm déclarées dans
package.jsonn'atteignent donc jamais la SBOM. Il écrit tout de même un document valide avec tout ce qu'il a reconnu par ailleurs. - Installé ou déclaré. Avoir lancé une installation avant le scan peut compter davantage que le choix de l'outil. Sur une copie installée du même dépôt, un seul réglage de cataloger Syft décide si les paquets npm installés apparaissent ou non.
- Dépendances de développement. Trivy les exclut par défaut et cdxgen les inclut : un même lockfile donne donc deux réponses à la question « que contient ce projet ».
- Noms et versions. Les outils identifient certains composants sous des types de package URL différents, ou l'un épingle une GitHub Action à un SHA de commit là où un autre indique un tag. Une recherche de vulnérabilités fondée sur le mauvais identifiant donne une réponse fausse mais assurée.
- Aucun manifeste. Le dépôt anthropics/claude-code n'a aucun manifeste de dépendances, et son paquet npm encapsule un binaire précompilé. Ce que renvoie chaque outil en dit plus sur l'outil que sur le projet.
Ce qu'ils ratent tous : les dépendances cachées
La limite la plus profonde est commune. Un scanner lit le lockfile ou la sortie du build et en déduit ce qui y est entré, après coup. Tout ce que le build a récupéré en dehors de ces fichiers n'atteint jamais la SBOM. Ce sont les dépendances cachées :
- Les hooks d'installation. Les scripts npm
preinstalletpostinstalls'exécutent pendant l'installation et peuvent télécharger davantage de code. C'est ainsi que s'est exécuté le ver Shai-Hulud. - Les scripts de build, comme les scripts de build Rust qui téléchargent ce dont ils ont besoin au moment du build.
- Les images de base et leurs couches de système d'exploitation dans un build de conteneur, qu'aucun lockfile de langage ne liste.
- Les paquets restaurés depuis les caches CI, qui peuvent ne pas correspondre au lockfile actuel. Voir ce que le cache GitHub Actions dissimule.
- Les outils de build installés par les étapes de configuration, avec leurs propres arbres de dépendances.
- Les versions transitives résolues au moment du build lorsque le lockfile est absent, périmé ou non utilisé par une installation figée. Voir les dépendances transitives.
Scanner la sortie après coup ne comble pas la lacune. Un binaire terminé, surtout du code compilé comme Rust, oblige le scanner à deviner ce qui y est entré. Les scanners SCA commerciaux travaillent à partir des mêmes types de fichiers et partagent les mêmes angles morts. CRACI a trouvé des paquets vulnérables que Snyk et Aikido n'avaient pas signalés, parce que ces composants n'ont jamais figuré dans ce qu'ils ont scanné.
Les outils font aussi partie de votre chaîne d'approvisionnement
Un scanner s'exécute dans votre CI avec un accès à votre code et souvent à vos secrets. En mars 2026, l'avis de sécurité d'Aqua Security (CVE-2026-33634) a décrit une release malveillante Trivy v0.69.4 et des tags trivy-action et setup-trivy empoisonnés qui volaient des identifiants sur les runners CI. Épinglez les actions de scanner à des SHA de commit complets et consultez l'avis pour les versions que vous utilisez.
Comment vérifier votre propre SBOM
- Exécutez deux générateurs sur le même commit et comparez les package URLs qu'ils signalent.
- Vérifiez si le dépôt commite un lockfile et si la CI installe à partir de celui-ci avec une installation figée.
- Scannez après l'étape d'installation aussi bien qu'avant, et comparez.
- Comparez la liste aux téléchargements visibles dans votre log de build, y compris les étapes de configuration et les restaurations de cache.
Si les listes diffèrent, la SBOM que vous publiez dépend de l'outil que vous avez lancé, et non de ce que vous avez livré.
Enregistrez plutôt le build
CRACI voit le trafic ; pas les scanners. C'est un runner GitHub Actions qui voit le trafic réseau entrant dans chaque build : sa SBOM enregistre donc chaque paquet récupéré par le job, à tous les niveaux de l'arbre, y compris les dépendances cachées et les paquets restaurés depuis les caches CI. Il n'y a aucun répertoire à indiquer ni aucun cataloger à choisir. Lorsqu'un enregistrement n'a pas pu tout voir, par exemple parce qu'un job a autorisé du trafic non surveillé, la SBOM le signale par son état de complétude.
L'enregistrement compte aussi parce que les builds sont rarement reproductibles. Construisez deux fois de suite le même commit, et le gestionnaire de paquets peut résoudre et installer dans un ordre différent : le second build peut donc contenir d'autres paquets. Seule la SBOM enregistrée pendant le build qui a produit une release prouve ce que contient cette release.
Gardez Syft ou Trivy pour les images et binaires tiers que vous n'avez pas construits. Pour vos propres releases, consultez les SBOM au build ou réservez une démo pour comparer une SBOM enregistrée à celle de votre outil actuel sur l'un de vos dépôts.
Générateurs de SBOM open source : questions fréquentes
Lequel est le meilleur pour les SBOM, Syft ou Trivy ?
Ils sont conçus pour des tâches différentes. Syft est un générateur de SBOM dédié, avec de nombreux catalogers et des attestations signées ; Trivy est un scanner de sécurité qui écrit des SBOM parmi ses sorties. Tous deux lisent les fichiers qu'ils ont devant eux : sur un même dépôt, la principale différence tient donc généralement à la présence d'un lockfile commité et au fait que les dépendances aient été installées avant le scan.
Pourquoi ma SBOM n'affiche-t-elle aucune dépendance ?
Le plus souvent parce que le dépôt ne commite aucun lockfile et que rien n'a été installé avant le scan. Un générateur qui lit les lockfiles ou les paquets installés n'a alors rien à lire, et il écrit tout de même une SBOM valide. Commitez le lockfile, ou scannez après l'étape d'installation.
Trivy inclut-il les dépendances de développement dans la SBOM ?
Pas par défaut. La documentation Node.js de Trivy indique qu'il ne signale pas les dépendances de développement, sauf si vous passez --include-dev-deps. cdxgen, à l'inverse, analyse les lockfiles et inclut les dépendances de développement. Deux outils peuvent diverger sur un même projet pour cette seule raison.
Peut-on se fier à une SBOM issue d'un générateur open source ?
Pour ce qu'il a lu, oui. La question est ce qu'il n'a pas lu : caches, outils de build, téléchargements, scripts d'installation et binaires sans métadonnées de paquet. Considérez une SBOM scannée comme la description des fichiers que vous avez indiqués à l'outil, et non du build qui a produit votre release.
Quel est le meilleur outil SBOM ?
Pour les logiciels que vous construisez vous-même, la SBOM la plus complète vient de l'enregistrement du build plutôt que du scan de fichiers. CRACI enregistre chaque paquet récupéré par chaque job GitHub Actions, y compris depuis les caches, et a trouvé des paquets vulnérables que Snyk et Aikido n'avaient pas signalés. Pour les images et binaires tiers que vous n'avez pas construits, un scanner comme Syft ou Trivy reste le choix pratique.
Comparez une SBOM enregistrée à celle de votre scanner
Exécutez un workflow GitHub Actions sur CRACI et comparez sa SBOM des paquets récupérés à ce qu'ont signalé Syft, Trivy ou cdxgen.
Réserver une démo