Le 11 septembre 2026, les premières obligations de déclaration du Cyber Resilience Act (CRA) sont entrées en vigueur dans l’Union européenne. Concrètement, les éditeurs de logiciels et les fabricants de produits connectés doivent désormais savoir répondre à une question simple en apparence : quels composants, quelles bibliothèques et quelles versions tournent réellement dans leurs conteneurs. Le SBOM, ou nomenclature logicielle, est l’outil qui répond à cette question. Ce tutoriel vous montre comment en générer un, le lire, détecter les vulnérabilités qu’il révèle, puis l’intégrer dans un pipeline CI/CD complet avec deux outils open source devenus la référence du secteur : Syft et Grype, développés par Anchore.

À l’issue de ce guide, vous saurez construire une image Docker, en extraire un inventaire précis de ses dépendances aux formats CycloneDX et SPDX, scanner ces inventaires pour trouver des failles connues, automatiser le tout dans GitHub Actions, attacher le résultat à votre image via Docker Buildx, puis étendre la démarche à un cluster Kubernetes. Le projet final est fonctionnel de bout en bout et reproductible sur votre machine en moins d’une heure.

Pourquoi le SBOM devient incontournable en Europe en 2026

Le Cyber Resilience Act est entré en vigueur le 10 décembre 2024, mais son calendrier d’application s’étale sur plusieurs années. Les obligations de déclaration des incidents et des vulnérabilités activement exploitées s’appliquent depuis le 11 septembre 2026, tandis que les obligations principales du règlement, dont la documentation technique intégrant la nomenclature logicielle, deviennent contraignantes le 11 décembre 2027. Pour les équipes qui publient des produits contenant des éléments numériques vendus dans l’UE, ce n’est plus une question de conformité lointaine : le compte à rebours a commencé.

Le texte impose aux fabricants d’identifier et de documenter les vulnérabilités et composants de leurs produits, notamment en établissant une nomenclature logicielle dans un format lisible par machine, couvrant au minimum les dépendances de premier niveau. C’est exactement ce que produisent Syft, Trivy ou les fonctions natives de Docker Buildx. Au-delà de la contrainte réglementaire, le SBOM sert un objectif opérationnel très concret : quand une CVE critique tombe un vendredi soir, un inventaire à jour permet de savoir en quelques secondes si vous êtes exposé, plutôt que de fouiller manuellement des dizaines d’images. Un exemple récent illustre ce mécanisme : la vulnérabilité CVE-2026-12569, ajoutée au catalogue des vulnérabilités exploitées connues de la CISA le 26 juin 2026, a mis en évidence l’intérêt d’un SBOM à jour pour déterminer rapidement si un composant vulnérable était présent dans une chaîne de build.

Ce tutoriel s’adresse aux développeurs, ingénieurs DevOps et responsables sécurité qui doivent industrialiser cette pratique sans y passer des semaines. On part de zéro, on construit un projet complet, et on termine avec un pipeline qui génère, scanne et publie automatiquement un SBOM à chaque build. Chaque étape est accompagnée d’exemples de commandes exécutables et de sorties réelles, pour que vous puissiez suivre le tutoriel en parallèle sur votre propre machine plutôt que de simplement lire de la théorie.

Le contexte français ajoute une couche supplémentaire à cette obligation européenne. L’ANSSI recommande depuis plusieurs années déjà l’inventaire systématique des composants tiers dans les produits critiques, une pratique qui converge désormais avec les exigences du CRA plutôt que de s’y opposer. Pour les équipes qui ont déjà mis en place un scanner de conteneurs comme Trivy ou un outil de durcissement Kubernetes, l’ajout d’une génération SBOM systématique reste une extension naturelle du pipeline existant plutôt qu’un chantier séparé. C’est précisément l’angle retenu ici : construire sur ce que vous avez probablement déjà, sans tout réinventer.

Comparer les outils : Syft, Trivy et Docker Scout

Avant de choisir un outil, il est utile de savoir où chacun excelle. Le marché de la génération SBOM ne se limite pas à Syft, même si c’est l’outil retenu comme fil conducteur de ce tutoriel pour sa précision et sa large adoption dans l’écosystème Anchore, Grype compris. Trivy, développé par Aqua Security, combine génération de SBOM et scan de vulnérabilités dans un seul binaire, ce qui simplifie l’installation au prix d’un couplage plus fort entre les deux fonctions. Docker Scout, intégré nativement à Docker Desktop et à Buildx, séduit par sa simplicité d’usage directement depuis les commandes Docker habituelles, sans installation d’outil tiers.

OutilÉditeurGénère un SBOMScanne les vulnérabilitésScan de cluster Kubernetes
SyftAnchoreOui, formats multiplesNon (rôle de Grype)Via scripts, pas nativement
GrypeAnchoreNonOui, à partir d’un SBOM ou d’une imageNon
TrivyAqua SecurityOuiOui, en un seul outilOui, sous-commande dédiée
Docker ScoutDocker Inc.Oui, via BuildxOui, intégréNon

Dans la pratique, ces outils ne s’excluent pas mutuellement. Beaucoup d’équipes matures font tourner Syft et Grype pour la précision du SBOM de référence, tout en gardant Trivy comme filet de sécurité rapide sur l’ensemble du cluster, un peu comme deux relecteurs indépendants sur le même code. Ce tutoriel se concentre sur Syft et Grype parce que leur séparation stricte entre génération et scan illustre le mieux la mécanique interne d’un SBOM, ce qui reste pédagogiquement précieux même si vous finissez par adopter Trivy en production pour sa simplicité opérationnelle.

Le choix dépend aussi de la taille de votre équipe. Une petite équipe qui gère un nombre limité de services tire souvent plus de valeur d’un outil unique comme Trivy, qui réduit la surface de maintenance et le nombre de bases de données à synchroniser. Une organisation plus grande, avec des équipes sécurité et plateforme distinctes, bénéficie davantage de la séparation Syft-Grype, qui permet à l’équipe plateforme de posséder la génération du SBOM pendant que l’équipe sécurité pilote indépendamment les règles de scan et les seuils de blocage.

CycloneDX contre SPDX : quel format choisir

Deux formats dominent l’écosystème SBOM et il vaut mieux comprendre leurs différences avant de lancer la première commande. CycloneDX, maintenu sous l’égide de l’OWASP, a été conçu dès le départ avec une orientation sécurité : gestion des vulnérabilités, chaîne d’approvisionnement, signatures cryptographiques. SPDX, devenu la norme ISO/IEC 5962:2021, vient historiquement du monde de la conformité des licences open source, même s’il couvre aujourd’hui aussi les cas d’usage sécurité. Les deux sont largement supportés par Syft, qui peut générer l’un, l’autre, ou les deux à la fois.

CritèreCycloneDXSPDX
Organisme maintainerOWASPLinux Foundation / ISO
Version actuelle de la spécification1.62.3 (ISO/IEC 5962:2021)
Orientation d’origineSécurité et gestion des vulnérabilitésConformité licences et provenance
Sérialisations supportéesJSON, XMLJSON, XML, tag-value
Support VEX natifOui (CycloneDX VEX)Via extensions
Adoption typiquePipelines DevSecOps, scannersAudits de licences, secteur public

Dans la pratique, la plupart des équipes génèrent les deux formats en parallèle plutôt que de trancher définitivement. CycloneDX s’impose naturellement quand l’objectif principal est le scan de vulnérabilités et la corrélation avec Grype ou Trivy. SPDX reste préférable si un client, un auditeur ou une administration exige explicitement ce format, ce qui reste fréquent dans les marchés publics européens. Ce tutoriel vous fait générer les deux, ce qui vous laisse le choix le moment venu.

Prérequis : outils, versions et compétences nécessaires

Avant de commencer, vérifiez que votre environnement dispose des éléments suivants. Aucun n’est exotique, mais les versions comptent, surtout pour les fonctionnalités d’attestation Buildx utilisées plus loin.

OutilVersion utilisée dans ce tutorielRôle
Syftv1.51.1 (27 août 2026)Génération du SBOM
Grypev0.118.0 (27 août 2026)Scan de vulnérabilités à partir d’un SBOM
Docker Engine + BuildxDernière version stableConstruction d’image et attestations SBOM natives
TrivyDernière version stableScan complémentaire et lecture de SBOM existants
Node.jsLTS activeApplication de démonstration
kubectlCompatible avec votre clusterÉtape Kubernetes en fin de tutoriel
Compte GitHubPipeline GitHub Actions

Vous aurez aussi besoin d’un terminal Linux, macOS ou WSL2 sous Windows, ainsi que des droits pour exécuter le démon Docker localement. Aucune connaissance préalable de la sécurité applicative n’est requise, mais une familiarité de base avec Docker et un pipeline CI accélérera votre progression. Comptez environ 45 minutes pour dérouler l’ensemble des étapes, un peu plus si vous testez chaque variante de commande proposée.

Si vous suivez ce tutoriel derrière un proxy d’entreprise ou sur un poste géré par une politique de sécurité stricte, prévoyez d’autoriser sortant les domaines github.com, anchore.io et le registre de conteneurs que vous utilisez. Les scripts d’installation de Syft et Grype téléchargent le binaire depuis les releases GitHub du projet, et Grype télécharge sa base de vulnérabilités depuis l’infrastructure Anchore au premier lancement. Sans ces accès, l’installation semble réussir mais le premier scan échoue silencieusement.

Le projet complet que vous allez construire

Plutôt que de manipuler des exemples abstraits, ce tutoriel s’appuie sur une petite application Node.js volontairement construite avec une dépendance datée, pour que Grype ait quelque chose de concret à détecter. La structure finale du projet ressemble à ceci :

sbom-demo/
├── Dockerfile
├── package.json
├── server.js
├── sbom/
│   ├── sbom-cyclonedx.json
│   └── sbom-spdx.json
└── .github/
    └── workflows/
        └── sbom-pipeline.yml

Voici le code de l’application, une API minimaliste en Express :

// server.js
const express = require('express');
const app = express();

app.get('/', (req, res) => {
  res.json({ status: 'ok', service: 'sbom-demo' });
});

app.listen(3000, () => {
  console.log('sbom-demo écoute sur le port 3000');
});
{
  "name": "sbom-demo",
  "version": "1.0.0",
  "main": "server.js",
  "dependencies": {
    "express": "4.18.2"
  }
}

Cette version fixée d’Express n’est pas choisie au hasard : elle vous permettra plus loin de voir Grype remonter des avis de sécurité réels plutôt qu’une liste vide, ce qui est nettement plus formateur qu’un exemple parfaitement propre. En production, vous remplaceriez évidemment cette version par la plus récente disponible.

Vous pouvez cloner cette structure localement en quelques commandes, sans dépendance externe autre que Node.js et Docker :

mkdir sbom-demo && cd sbom-demo
mkdir sbom
npm init -y
npm install [email protected] --save-exact

Une fois server.js et le Dockerfile créés comme indiqué ci-dessous, vous disposez d’un projet minimal mais complet, suffisant pour dérouler l’intégralité des douze étapes qui suivent sans avoir à improviser sur un vrai projet en cours de développement.

Étapes 1 à 3 : installer Syft, Grype et vérifier l’environnement

Étape 1. Installez Syft via le script officiel d’Anchore, qui place le binaire dans votre PATH :

curl -sSfL https://raw.githubusercontent.com/anchore/syft/main/install.sh \
  | sh -s -- -b /usr/local/bin

syft version

Sortie attendue :

Application:        syft
Version:            1.51.1
BuildDate:           2026-08-27T10:12:44Z
GitCommit:           a3f9c21
Platform:            linux/amd64

Étape 2. Installez Grype de la même façon. Les deux outils partagent la même logique de packaging chez Anchore, donc la commande est quasiment identique :

curl -sSfL https://raw.githubusercontent.com/anchore/grype/main/install.sh \
  | sh -s -- -b /usr/local/bin

grype version

Étape 3. Vérifiez que Docker fonctionne et que la base de données de vulnérabilités de Grype se télécharge correctement. Grype maintient un cache local des avis de sécurité qu’il faut rafraîchir régulièrement :

docker version --format '{{.Server.Version}}'
grype db update
grype db status

Si grype db status affiche une base valide et une date de construction récente, votre environnement est prêt. Passez à l’étape suivante.

Étape 4 : préparer une image Docker de démonstration

Créez le Dockerfile suivant à la racine du projet. Il reste volontairement simple pour que l’attention reste sur le SBOM plutôt que sur la construction d’image :

FROM node:20-slim

WORKDIR /app
COPY package.json .
RUN npm install --production
COPY server.js .

EXPOSE 3000
CMD ["node", "server.js"]

Construisez l’image localement :

docker build -t sbom-demo:1.0.0 .

Une fois l’image construite, vous disposez d’un artefact concret sur lequel générer votre premier inventaire. Notez que Syft sait aussi analyser un répertoire source directement, sans passer par une image Docker, ce qui est utile pour auditer un dépôt avant même le premier build.

Étape 5 : générer votre premier SBOM avec Syft

Lancez la commande suivante pour produire un SBOM au format CycloneDX JSON, qui est aujourd’hui le format le plus utilisé pour la corrélation avec des scanners de vulnérabilités :

syft sbom-demo:1.0.0 -o cyclonedx-json > sbom/sbom-cyclonedx.json

Syft accepte plusieurs syntaxes d’adressage selon l’origine de l’image : docker:sbom-demo:1.0.0 pour forcer la lecture via le démon Docker local, ou registry:mon-registre/sbom-demo:1.0.0 pour analyser une image directement depuis un registre distant sans la télécharger localement au préalable. Cette dernière option est particulièrement utile en CI, où tirer une image complète juste pour l’inventorier gaspille du temps de build.

Extrait de la sortie console pendant l’analyse :

 ✔ Loaded image
 ✔ Parsed image
 ✔ Cataloged contents         324c778a9a3e
   ├── ✔ Packages                        [61 packages]
   ├── ✔ File digests                    [412 files]
   ├── ✔ File metadata                   [412 locations]
   └── ✔ Executables                     [9 executables]

Soixante et un paquets identifiés pour une image aussi minimaliste : c’est la réalité de l’écosystème Node.js, où une seule dépendance directe entraîne souvent des dizaines de sous-dépendances transitives, chacune étant une surface d’attaque potentielle que le SBOM rend enfin visible.

Étape 6 : générer un SBOM complémentaire au format SPDX

Répétez l’opération pour produire la version SPDX du même inventaire. Comme les deux commandes analysent la même image, elles produisent des ensembles de composants identiques, seule la structure du fichier change :

syft sbom-demo:1.0.0 -o spdx-json > sbom/sbom-spdx.json

Si un outil en aval de votre chaîne exige une version précise de la spécification plutôt que la dernière par défaut, épinglez-la explicitement. C’est une pratique recommandée dès que plusieurs équipes consomment le même SBOM, pour éviter qu’une mise à jour de Syft ne casse silencieusement un parseur en aval :

syft sbom-demo:1.0.0 -o [email protected] > sbom/sbom-cyclonedx-v15.json
syft sbom-demo:1.0.0 -o [email protected] > sbom/sbom-spdx-v22.json

Vous disposez désormais de deux nomenclatures complètes et lisibles par machine. L’étape suivante consiste à comprendre ce qu’elles contiennent réellement.

Étape 7 : lire et interpréter le contenu d’un SBOM

Un fichier CycloneDX JSON contient, pour chaque composant, un nom, une version, un type (bibliothèque, système d’exploitation, framework), un identifiant unique appelé PURL (Package URL), et souvent une licence déclarée. Isolez rapidement les informations essentielles avec jq :

jq '.components[] | {name, version, purl}' sbom/sbom-cyclonedx.json | head -30
{
  "name": "express",
  "version": "4.18.2",
  "purl": "pkg:npm/[email protected]"
}
{
  "name": "body-parser",
  "version": "1.20.1",
  "purl": "pkg:npm/[email protected]"
}
{
  "name": "debian",
  "version": "12.7",
  "purl": "pkg:deb/debian/[email protected]"
}

Ce format PURL est la clé qui permet à Grype, Trivy ou n’importe quel autre scanner de corréler chaque composant avec des bases de vulnérabilités publiques comme la NVD ou les avis GitHub. Sans identifiant standardisé, cette corrélation automatique serait impossible à grande échelle. C’est précisément ce qui distingue un SBOM utile d’une simple liste de fichiers.

Un point mérite votre attention à ce stade : la distinction entre dépendances directes et transitives. Le fichier package.json du projet ne déclare qu’une seule dépendance, Express, mais le SBOM en révèle des dizaines. Ce sont ces dépendances transitives, invisibles dans votre code source mais bien présentes dans l’image finale, qui échappent le plus souvent à une revue de sécurité manuelle. Comptez le nombre de composants par type pour vous en rendre compte :

jq '.components | group_by(.type) | map({type: .[0].type, count: length})' sbom/sbom-cyclonedx.json

Sur l’image de démonstration, cette commande révèle typiquement une majorité de paquets npm transitifs, quelques bibliothèques système Debian héritées de l’image de base node:20-slim, et un seul paquet applicatif direct. C’est ce déséquilibre qui justifie l’automatisation : personne ne relit manuellement soixante dépendances transitives à chaque release.

Étape 8 : scanner les vulnérabilités avec Grype

C’est ici que le SBOM prend tout son sens : Grype consomme directement le fichier généré par Syft, sans avoir besoin de retélécharger ou de réanalyser l’image :

grype sbom:./sbom/sbom-cyclonedx.json

Exemple de sortie sur notre image de démonstration :

NAME       INSTALLED  FIXED-IN  TYPE  VULNERABILITY   SEVERITY
express    4.18.2     4.19.2    npm   GHSA-rv95-896h  Medium
qs         6.11.0     6.11.1    npm   GHSA-hrpp-h998  High
debian     12.7       12.8      deb   CVE-2026-xxxxx  Low

Grype accepte aussi des cibles directes sans passer par un SBOM préexistant, ce qui reste pratique pour un contrôle ponctuel :

grype docker:sbom-demo:1.0.0
grype registry:mon-registre/sbom-demo:1.0.0

Mais scanner à partir d’un SBOM déjà généré reste plus rapide en pipeline, puisque l’analyse du système de fichiers de l’image n’a lieu qu’une seule fois, chez Syft, et que Grype se contente ensuite de la corrélation avec sa base de vulnérabilités.

Étape 9 : chaîner Syft et Grype dans un seul pipeline

Pour un contrôle rapide en une seule commande, Syft peut transmettre sa sortie directement à Grype par un tube Unix, sans fichier intermédiaire :

syft sbom-demo:1.0.0 -o syft-json | grype

Cette approche convient bien à un contrôle manuel ou à un hook de pré-commit. En pipeline CI/CD, préférez toutefois conserver le fichier SBOM comme artefact persistant : vous en aurez besoin plus tard pour l’audit, pour la conformité CRA, ou pour comparer deux versions d’une même image sans reconstruire quoi que ce soit.

Étape 10 : automatiser la génération SBOM avec GitHub Actions

Voici un pipeline complet qui construit l’image, génère les deux SBOM, scanne les vulnérabilités et publie les fichiers en artefacts de build :

name: sbom-pipeline

on:
  push:
    branches: [main]

jobs:
  build-and-sbom:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Build image
        run: docker build -t sbom-demo:${{ github.sha }} .

      - name: Install Syft
        run: curl -sSfL https://raw.githubusercontent.com/anchore/syft/main/install.sh | sh -s -- -b /usr/local/bin

      - name: Install Grype
        run: curl -sSfL https://raw.githubusercontent.com/anchore/grype/main/install.sh | sh -s -- -b /usr/local/bin

      - name: Generate SBOM (CycloneDX)
        run: syft sbom-demo:${{ github.sha }} -o cyclonedx-json > sbom-cyclonedx.json

      - name: Generate SBOM (SPDX)
        run: syft sbom-demo:${{ github.sha }} -o spdx-json > sbom-spdx.json

      - name: Scan for vulnerabilities
        run: grype sbom:./sbom-cyclonedx.json --fail-on high

      - uses: actions/upload-artifact@v4
        with:
          name: sbom-artifacts
          path: sbom-*.json

L’option --fail-on high fait volontairement échouer le pipeline si une vulnérabilité de sévérité élevée ou critique est détectée, ce qui transforme le SBOM en véritable porte de sécurité plutôt qu’en simple documentation passive. Ajustez ce seuil selon la maturité de votre projet : un seuil trop strict dès le premier jour bloque souvent toute l’équipe sur des vulnérabilités historiques qu’il faut d’abord traiter séparément.

Étape 11 : attacher le SBOM à l’image avec Docker Buildx

Plutôt que de gérer le SBOM comme un fichier séparé, Docker Buildx permet de le générer comme une attestation liée directement à l’image, au moment même du build, et de la pousser vers le registre en même temps que les couches de l’image :

docker buildx build \
  --sbom=true \
  --tag mon-registre/sbom-demo:1.0.0 \
  --push .

Une fois l’image poussée, l’attestation SBOM voyage avec elle et peut être récupérée par quiconque a accès au registre, sans avoir besoin de reconstruire l’image ni de conserver un fichier séparé dans votre système de fichiers CI :

docker buildx imagetools inspect mon-registre/sbom-demo:1.0.0 \
  --format '{{ json .SBOM }}'

C’est l’approche recommandée dès que vous distribuez vos images au-delà de votre propre pipeline CI, par exemple vers des clients, des partenaires, ou une équipe de sécurité qui n’a pas accès à vos dépôts GitHub.

Étape 12 : générer un SBOM pour un cluster Kubernetes et se conformer au CRA

Un SBOM généré une fois au moment du build ne suffit pas si les images qui tournent réellement en production dérivent avec le temps, par exemple via des retags ou des correctifs à chaud. Pour inventorier ce qui est effectivement déployé, listez d’abord les images utilisées par votre cluster, puis analysez chacune d’elles :

kubectl get pods --all-namespaces \
  -o jsonpath="{range .items[*]}{.spec.containers[*].image}{'\n'}{end}" \
  | sort -u > images-en-prod.txt

while read -r image; do
  echo "=== $image ==="
  syft "registry:$image" -o cyclonedx-json > "sbom-$(echo $image | tr '/:' '__').json"
done < images-en-prod.txt

Vous obtenez ainsi un SBOM par image réellement déployée, et non plus seulement par image construite. C'est cette collection de fichiers, associée à un processus documenté de veille sur les vulnérabilités, qui constitue la brique technique attendue par le CRA pour la documentation des produits contenant des éléments numériques. Pour une conformité complète d'ici l'échéance du 11 décembre 2027, il faut aussi mettre en place un processus de traitement des vulnérabilités et un canal de déclaration, mais l'inventaire technique généré ici en est le socle indispensable.

Gardez une trace horodatée de chaque SBOM généré plutôt que d'écraser systématiquement le précédent. En cas de contrôle ou d'incident, la capacité à prouver quelle version d'un composant tournait en production à une date donnée pèse autant que l'inventaire lui-même. Un simple dépôt Git dédié, avec un commit par exécution du pipeline, suffit pour la plupart des équipes et évite de dépendre d'un outil d'archivage supplémentaire :

git -C sbom-archive add "sbom-$(date -u +%Y%m%dT%H%M%S).json"
git -C sbom-archive commit -m "SBOM automatique, build ${GITHUB_SHA}"

Cette archive devient la référence à présenter en cas de demande d'un client, d'un partenaire ou d'un organisme de contrôle, sans avoir à reconstruire une image passée pour retrouver ce qu'elle contenait.

Trivy propose une alternative pour ce même besoin, avec un sous-mode dédié qui scanne directement un cluster Kubernetes sans passer par une liste d'images manuelle :

trivy k8s --report summary cluster

Les deux approches sont complémentaires : Syft excelle dans la précision de l'inventaire par composant, Trivy dans la vue d'ensemble rapide au niveau du cluster.

Pièges courants à éviter

La plupart des équipes qui adoptent le SBOM commettent les mêmes erreurs, souvent parce que la documentation officielle des outils suppose déjà une certaine maturité DevSecOps. Voici les six pièges les plus fréquents observés dans des pipelines réels, du plus bénin au plus coûteux à corriger a posteriori.

  • Confondre le périmètre du scan avec le périmètre réel du produit. Un SBOM généré à partir de l'image finale ne reflète que ce qui est visible dans cette image, pas les outils de build, les dépendances de développement écartées du multi-stage, ni le code source complet du dépôt. Si votre obligation de conformité porte sur le produit dans son ensemble, complétez par une analyse du dépôt source avec syft dir:.
  • Ne pas épingler la version du format de sortie. Une mise à jour de Syft peut faire passer le format CycloneDX par défaut d'une version mineure à une autre, ce qui casse silencieusement un parseur en aval qui n'attendait pas ce changement de schéma.
  • Confondre génération et scan de vulnérabilités. Syft génère un inventaire, il ne détecte aucune faille par lui-même. Beaucoup de nouvelles équipes s'arrêtent après l'étape Syft en pensant avoir fait le travail de sécurité, alors que c'est Grype ou Trivy qui apporte la corrélation avec les bases de vulnérabilités.
  • Mal adresser l'image source. Utiliser docker: pour une image qui n'existe que sur un registre distant, ou l'inverse, produit une erreur ou pire, un SBOM vide sans message d'erreur explicite selon la version utilisée.
  • Ne générer qu'un seul format. Beaucoup de pipelines produisent uniquement du CycloneDX, puis se retrouvent bloqués quand un client ou un auditeur exige du SPDX six mois plus tard. Générer les deux dès le départ coûte une ligne de configuration supplémentaire.
  • Ne pas conserver les SBOM comme artefacts persistants. Si le fichier n'existe que le temps du job CI puis disparaît, vous perdez la capacité de répondre en cas d'audit rétroactif ou de nouvelle CVE découverte des mois plus tard sur un composant déjà déployé.

Dépannage : 8 problèmes fréquents et leurs solutions

Même avec une installation propre, certains comportements surprennent la première fois. Voici les symptômes les plus fréquemment rapportés par les utilisateurs de Syft et Grype, avec la cause probable et la commande de résolution.

  • Syft retourne zéro paquet sur une image scratch ou distroless. Ces images minimalistes n'embarquent souvent aucun gestionnaire de paquets détectable. Vérifiez que le binaire compilé lui-même contient des métadonnées (cas fréquent pour Go) avec syft --scope all-layers, qui inspecte aussi les couches intermédiaires du Dockerfile.
  • Grype signale des centaines de faux positifs sur une image de base standard. Mettez à jour la base de données avec grype db update avant chaque scan critique, les bases obsolètes génèrent des correspondances de version imprécises.
  • Le pipeline CI échoue avec une erreur de timeout au téléchargement de la base Grype. Mettez la base en cache entre les runs avec l'action actions/cache ciblant le répertoire ~/.cache/grype, plutôt que de la retélécharger à chaque exécution.
  • Le SBOM dépasse la limite de taille des artefacts CI. Compressez le fichier JSON avant upload, ou filtrez les composants système non pertinents avec syft --exclude si votre politique ne nécessite pas l'inventaire complet de l'OS de base.
  • docker buildx build --sbom=true échoue silencieusement. Cette fonctionnalité nécessite le driver BuildKit avec le builder docker-container, pas le driver par défaut. Créez d'abord un builder dédié avec docker buildx create --use.
  • Erreur d'authentification lors du scan d'une image sur un registre privé. Syft et Grype réutilisent la configuration Docker locale. Connectez-vous d'abord avec docker login avant de lancer syft registry:..., sinon l'outil tente un accès anonyme qui échoue.
  • Les versions de paquets détectées par Syft ne correspondent pas à celles installées réellement. Cela arrive quand une image a été patchée après coup sans reconstruction complète. Régénérez systématiquement le SBOM après toute modification de l'image, même mineure.
  • grype sbom:./fichier.json renvoie une erreur de format non reconnu. Vérifiez que le fichier a bien été généré en JSON et non en table texte lisible par un humain. La commande syft ... -o table produit un format d'affichage, pas un SBOM exploitable par Grype.

Astuces avancées pour aller plus loin

Une fois la chaîne de base maîtrisée, trois pratiques permettent de passer d'un simple inventaire à une véritable posture de sécurité de la chaîne d'approvisionnement logicielle.

Signez vos SBOM avec cosign pour garantir leur intégrité entre le moment de la génération et celui de la consultation. Sans signature, rien n'empêche un attaquant ayant compromis votre registre de substituer un SBOM falsifié masquant une dépendance vulnérable :

cosign attach sbom --sbom sbom/sbom-cyclonedx.json mon-registre/sbom-demo:1.0.0
cosign sign mon-registre/sbom-demo:1.0.0

Comparez deux versions d'une même image pour visualiser précisément ce qui a changé entre deux releases, une pratique utile avant tout déploiement en production sur un composant sensible :

diff <(jq -S '.components[].purl' sbom-v1.0.0.json) \
     <(jq -S '.components[].purl' sbom-v1.1.0.json)

Enfin, complétez votre SBOM par un document VEX (Vulnerability Exploitability eXchange) pour indiquer explicitement qu'une vulnérabilité détectée par Grype ne s'applique pas à votre contexte d'usage, par exemple parce que le code vulnérable n'est jamais exécuté dans votre configuration. Cette pratique évite de faire échouer un pipeline sur des faux positifs contextuels tout en conservant une trace documentée et auditable de la décision, ce qui est précisément ce qu'attendent les auditeurs CRA plutôt qu'une simple suppression silencieuse de l'alerte.

Pour les équipes qui veulent aller plus loin dans la traçabilité de la chaîne de build, le cadre SLSA (Supply-chain Levels for Software Artifacts) complète naturellement le SBOM. Là où le SBOM répond à la question « qu'est-ce qu'il y a dans mon image », SLSA répond à « comment cette image a-t-elle été construite et par qui ». Combiner une attestation de provenance SLSA avec un SBOM signé donne une chaîne de confiance complète, de la source jusqu'au registre, ce qui devient un argument de poids face à un client ou un auditeur qui pousse sur la robustesse de votre chaîne d'approvisionnement logicielle.

Questions fréquentes

Un SBOM est-il obligatoire pour toutes les entreprises en Europe ?

Le Cyber Resilience Act concerne les fabricants de produits comportant des éléments numériques vendus dans l'UE, avec des obligations qui montent en puissance jusqu'au 11 décembre 2027. Les très petites structures et certains cas d'usage spécifiques bénéficient de règles allégées, mais la tendance générale pousse vers une documentation SBOM systématique pour tout logiciel commercialisé. Attendre la date limite pour s'y mettre revient à devoir reconstruire rétroactivement l'historique de composants de dizaines de versions d'images, un travail bien plus lourd que d'automatiser la génération dès aujourd'hui.

Faut-il choisir entre Syft et Trivy ?

Non, les deux outils sont complémentaires plutôt que concurrents directs sur ce cas d'usage précis. Syft se concentre sur la génération de SBOM de haute précision, Trivy combine génération et scan dans un seul binaire et ajoute des fonctionnalités comme le scan direct de cluster Kubernetes. Beaucoup d'équipes utilisent Syft pour la génération fine et Trivy pour les contrôles rapides transversaux.

Le SBOM ralentit-il significativement le pipeline CI/CD ?

Sur une image applicative standard, la génération avec Syft prend généralement de quelques secondes à moins d'une minute. Le scan Grype à partir d'un SBOM déjà généré est encore plus rapide puisqu'il n'a pas besoin de réanalyser le système de fichiers de l'image. L'essentiel du temps supplémentaire vient du téléchargement initial de la base de vulnérabilités, largement absorbé par la mise en cache.

CycloneDX et SPDX peuvent-ils cohabiter dans le même projet ?

Oui, rien n'empêche de générer les deux formats à chaque build, comme ce tutoriel le montre à l'étape 6. Cela évite de devoir choisir prématurément et couvre à la fois les besoins de scan de sécurité et les exigences de conformité de licences.

Comment gérer les vulnérabilités sans correctif disponible ?

Documentez la décision dans un fichier VEX plutôt que d'ignorer silencieusement l'alerte. Indiquez si le composant vulnérable est effectivement exploitable dans votre contexte, et prévoyez une date de réévaluation. C'est cette traçabilité qui distingue une gestion mature des vulnérabilités d'un simple contournement de contrôle CI.

Un SBOM généré par Syft est-il valable pour un audit CRA ?

Le format technique produit par Syft en CycloneDX ou SPDX correspond aux formats lisibles par machine attendus par le règlement. Le SBOM seul ne suffit toutefois pas à assurer la conformité complète : il doit s'accompagner d'un processus documenté de gestion des vulnérabilités, d'un canal de déclaration et d'une mise à jour régulière de l'inventaire, comme démontré à l'étape 12 de ce tutoriel.

Peut-on générer un SBOM sans construire l'image Docker au préalable ?

Oui. Syft peut analyser directement un répertoire source avec syft dir:., ou une image déjà publiée sur un registre distant avec syft registry:..., sans jamais construire ni télécharger l'image localement.

Que faire si Grype et Trivy donnent des résultats différents sur la même image ?

Ces divergences sont fréquentes et proviennent de bases de données de vulnérabilités et de logiques de correspondance de version légèrement différentes entre les deux outils. La bonne pratique consiste à faire tourner les deux scanners en parallèle plutôt que de choisir arbitrairement l'un des deux, et à traiter toute alerte remontée par au moins un des deux outils comme un signal à investiguer.

Combien de temps faut-il conserver les SBOM archivés ?

Il n'existe pas encore de durée légale fixe et harmonisée à l'échelle européenne pour l'archivage des SBOM dans le cadre du CRA. En pratique, la plupart des équipes s'alignent sur la durée de support annoncée du produit, souvent plusieurs années, en conservant un SBOM par version publiée plutôt qu'un seul instantané régulièrement écrasé. Un simple dépôt Git versionné, comme montré à l'étape 12, suffit pour cet usage sans nécessiter d'outil d'archivage dédié.