ITSkillsCenter
Business Digital

Générer un SBOM CycloneDX 1.7 conforme Cyber Resilience Act

12 min de lecture

📍 Guide principal du sujet : Pipeline SAST DAST SCA 2026 : architecture, outils et intégration CI/CD
Ce tutoriel se concentre sur la génération opérationnelle d’un SBOM CycloneDX 1.7. Pour la vue d’ensemble de la sécurité supply-chain (signing, scanning, gouvernance), voir aussi Sécurité supply-chain logiciel : SBOM, signing, scanning.

Pourquoi générer un SBOM CycloneDX 1.7 en 2026

Le Software Bill of Materials s’impose comme le passeport numérique d’un produit logiciel. La spécification CycloneDX 1.7, publiée par OWASP le 25 février 2026, étend la version 1.6 avec le support de la Cryptographic Bill of Materials (CBOM), des External Components, des contraintes de distribution TLP, des Data Provenance & Citations, et un name-value store extensible. Cette richesse en fait le format de référence pour répondre aux exigences du Cyber Resilience Act européen, dont les obligations sur la transparence des composants entrent progressivement en vigueur jusqu’en décembre 2027.

Au-delà de la conformité, un SBOM bien tenu sert trois cas d’usage opérationnels. Le premier est la réponse à incident : quand une CVE critique tombe (Log4Shell, XZ-Utils backdoor), une requête sur les SBOM permet en quelques secondes d’identifier les services impactés. Le deuxième est l’audit fournisseur : exiger un SBOM CycloneDX dans tout contrat avec un éditeur tiers donne une vue indépendante du code embarqué. Le troisième est le diff inter-versions : comparer le SBOM avant et après une mise à jour révèle l’introduction de nouvelles dépendances ou la disparition d’une bibliothèque attendue. Ce tutoriel construit pas-à-pas une chaîne de génération avec Syft 1.44, Trivy 0.70 et cdxgen 11, puis attache le SBOM à l’image OCI via cosign et documente les CVE non exploitables avec VEX.

Prérequis

  • Une machine Linux ou macOS avec Docker installé.
  • Un projet applicatif avec un manifest de dépendances (package-lock.json, go.sum, requirements.txt, etc.) ET/OU une image conteneur publiée.
  • Un compte sur un registre OCI (Docker Hub, GHCR, GitLab Container Registry).
  • Niveau attendu : intermédiaire DevOps, à l’aise avec la ligne de commande et JSON.
  • Temps estimé : 75 minutes pour la chaîne complète, 30 minutes supplémentaires pour automatiser dans la CI.

Étape 1 — Comprendre les trois axes du SBOM CycloneDX

Un SBOM ne se résume pas à une liste de dépendances. La spécification distingue trois familles de relations qu’un consommateur attend de retrouver. Les composants sont l’inventaire à plat : nom, version, hash, type (library, framework, OS, file), licence, source. Les dépendances expriment le graphe de relations entre composants — qui dépend de qui, en première ou en énième transitive. Les vulnérabilités et VEX indiquent les CVE connues affectant les composants et la position de l’éditeur sur leur exploitabilité réelle dans son contexte.

Un SBOM publié sans dépendances explicites est de qualité médiocre : on sait qu’une bibliothèque est présente sans savoir si elle est utilisée directement ou tirée par transitivité. Un SBOM sans vulnérabilités est seulement un état des lieux à un instant T. Un SBOM avec VEX est un objet vivant qui dialogue avec les scanners et permet une triage automatisé. La spécification 1.7 facilite ce dernier point en standardisant les champs analysis.state et analysis.justification.

Étape 2 — Installer Syft, l’outil de référence pour les SBOM

Syft, maintenu par Anchore sous licence Apache 2.0, est l’outil le plus polyvalent pour générer un SBOM. Il scanne les filesystems, les images OCI, les archives tar, les directories de dépôt Git, et reconnaît plus de 25 écosystèmes (npm, pip, gem, gomod, cargo, maven, packagist, etc.). La version v1.44.0, publiée le 1er mai 2026, ajoute le support de l’architecture linux-riscv64 et améliore le parsing des aliases dans les yarn.lock.

curl -sSfL https://get.anchore.io/syft | sudo sh -s -- -b /usr/local/bin
syft version

L’installation par script télécharge le binaire signé depuis GitHub Releases et l’installe dans /usr/local/bin. Vérifier la sortie : version 1.44.0 ou supérieure, OS détecté correctement. Pour une intégration CI Docker, l’image officielle anchore/syft:v1.44.0 évite l’étape d’installation et garantit la reproductibilité du scan d’un build à l’autre.

Étape 3 — Générer un SBOM CycloneDX d’un projet local

Pour un projet en cours de développement, scanner le répertoire source produit un SBOM qui reflète exactement les dépendances déclarées. La sortie au format cyclonedx-json est lisible par GitHub Code Scanning, GitLab, DefectDojo et la majorité des outils de gestion des vulnérabilités.

cd /chemin/vers/projet
syft scan dir:. \
  -o cyclonedx-json=sbom.cdx.json \
  -o spdx-json=sbom.spdx.json \
  -o table

Trois sorties sont produites simultanément : CycloneDX pour les outils OWASP-compatibles, SPDX pour les outils plus orientés Linux Foundation (Tern, FOSSology), et un tableau lisible en console pour vérification immédiate. Le fichier sbom.cdx.json contient un objet JSON structuré avec une racine bomFormat: "CycloneDX" et specVersion: "1.7", suivi de la liste des composants et de leur graphe de dépendances.

Étape 4 — Scanner une image OCI et capturer les couches OS

Pour un produit déployé en conteneur, le SBOM doit refléter à la fois les dépendances applicatives et les paquets OS de l’image de base. Syft scanne l’image en assemblant les deux niveaux automatiquement.

syft scan registry:ghcr.io/votreorg/votreapp:v1.2.3 \
  -o cyclonedx-json=sbom-image.cdx.json \
  --scope all-layers

L’option --scope all-layers oblige Syft à parcourir toutes les couches de l’image, y compris celles supprimées par un RUN rm ultérieur — ce qui est nécessaire pour un SBOM complet, parce qu’un fichier supprimé reste présent dans une couche intermédiaire et peut être récupéré par un attaquant qui a accès à l’image. Sans cette option, Syft scanne uniquement la couche finale (squashed) et passe à côté des paquets temporairement installés pour le build.

Étape 5 — Compléter avec cdxgen pour les écosystèmes spécifiques

Syft excelle sur les écosystèmes courants mais peut être moins précis sur des stacks plus marginales (Erlang, Lua, Dart, Haskell) ou sur l’analyse profonde des dépendances Java avec gradle. cdxgen, maintenu par CycloneDX/AppThreat, complète le panorama avec un support spécialisé d’environ 40 écosystèmes et une intégration native du deep scan Java.

npm install -g @cyclonedx/cdxgen
cdxgen -t java --deep -o sbom-java.cdx.json .

L’option --deep active l’analyse à l’exécution pour suivre les classloaders, ce qui révèle des dépendances qu’un parse statique du pom.xml ou du build.gradle manquerait. Pour un projet polyglotte, lancer syft et cdxgen séparément puis fusionner les SBOM avec cyclonedx-cli merge --input-files sbom-syft.cdx.json sbom-cdxgen.cdx.json --output-file sbom-merged.cdx.json (les fichiers sont passés individuellement après --input-files, sans wildcard). Le format CycloneDX supporte nativement la fusion, ce qui évite les doublons.

Étape 6 — Enrichir le SBOM avec les vulnérabilités via Trivy

Trivy 0.70 sait scanner un SBOM existant (trivy sbom) pour reporter les CVE des composants listés. Pour obtenir un SBOM CycloneDX enrichi avec les vulnérabilités embarquées dans le même fichier, le pattern recommandé est de regénérer le SBOM depuis l’image avec trivy image --scanners vuln --format cyclonedx, qui produit un document contenant à la fois les composants et les vulnerabilities[].

# Pour produire un SBOM CycloneDX enrichi avec les vulnérabilités, regénérer
# directement depuis l'image avec --scanners vuln, plutôt que de re-scanner le SBOM
trivy image \
  --scanners vuln \
  --format cyclonedx \
  --output sbom-with-vulns.cdx.json \
  ghcr.io/votreorg/votreapp:v1.2.3

# Pour seulement lister les CVE d'un SBOM existant (sortie JSON Trivy classique) :
trivy sbom sbom-image.cdx.json --format json --output cve-report.json

Le fichier sbom-with-vulns.cdx.json ainsi généré contient une section vulnerabilities[] avec, pour chaque CVE, l’identifiant, la sévérité CVSS, l’URL de l’advisory, le composant affecté et la version corrigée si elle existe. Cette représentation enrichie est exactement ce que les plateformes de gestion des vulnérabilités attendent en entrée : DefectDojo l’ingère via son endpoint /api/v2/import-scan/ avec le scanner type CycloneDX Scan, et déduplique automatiquement avec les findings d’autres outils.

Étape 7 — Documenter les CVE non exploitables avec VEX

Toutes les CVE détectées ne sont pas exploitables dans votre contexte : la fonction vulnérable n’est pas appelée, l’attaque exige une configuration que vous n’avez pas, ou une mitigation runtime bloque la surface. Le format VEX (Vulnerability Exploitability eXchange), normalisé dans CycloneDX 1.4 et étendu en 1.7, permet de documenter ces analyses de manière structurée et machine-lisible.

bomFormat: "CycloneDX"
specVersion: "1.7"
serialNumber: "urn:uuid:f1b1f1b1-1111-2222-3333-444455556666"
version: 1
metadata:
  timestamp: "2026-05-06T10:00:00Z"
  component:
    bom-ref: "pkg:image/votreapp@sha256:abc123def456"
    type: "container"
    name: "votreapp"
    version: "1.2.3"
vulnerabilities:
  - id: "CVE-2024-12345"
    source:
      name: "NVD"
      url: "https://nvd.nist.gov/vuln/detail/CVE-2024-12345"
    affects:
      - ref: "pkg:image/votreapp@sha256:abc123def456"
    analysis:
      state: "not_affected"
      justification: "code_not_reachable"
      detail: "Notre code n'invoque jamais la fonction vulnérable openssl_sign_old(). Vérifié avec CodeQL le 2026-04-15."
      response: ["will_not_fix"]

Cinq valeurs de state sont autorisées : resolved, resolved_with_pedigree, exploitable, in_triage, false_positive, not_affected. Neuf valeurs de justification couvrent les raisons techniques (code_not_present, code_not_reachable, requires_configuration, requires_dependency, requires_environment, protected_by_compiler, protected_at_runtime, protected_at_perimeter, protected_by_mitigating_control). Cette structure normalisée évite que chaque équipe invente son propre vocabulaire et permet aux outils en aval de filtrer automatiquement.

Étape 8 — Attacher le SBOM à l’image OCI via cosign

Un SBOM publié dans un fichier séparé sur un serveur web peut être altéré ou perdu. La pratique 2026 publie le SBOM comme attestation in-toto signée directement attachée à l’image OCI via cosign attest. La commande cosign attach sbom existe encore mais est marquée dépréciée par le projet Sigstore depuis 2024 : elle attache le SBOM sans le signer, ce qui n’apporte aucune garantie d’authenticité. cosign attest est la voie recommandée car elle combine attachement et signature en une seule attestation vérifiable.

IMAGE=ghcr.io/votreorg/votreapp:v1.2.3
DIGEST=$(crane digest $IMAGE)

# Étape recommandée : signer l'image puis publier le SBOM comme attestation signée
cosign sign --key cosign.key ${IMAGE}@${DIGEST}
cosign attest --predicate sbom-with-vulns.cdx.json \
  --type cyclonedx \
  --key cosign.key \
  ${IMAGE}@${DIGEST}

Deux opérations complémentaires : cosign sign signe l’image elle-même (l’identité de l’éditeur), cosign attest publie le SBOM comme attestation cryptographiquement signée au format in-toto, attachée à l’image dans le registre OCI sous l’extension .att. Le consommateur récupère et vérifie l’attestation avec cosign verify-attestation --type cyclonedx --key cosign.pub ${IMAGE}@${DIGEST}. Si la signature ne correspond pas, l’attestation est rejetée — un attaquant qui aurait altéré le SBOM ne peut pas faire passer son SBOM pour authentique.

Erreurs fréquentes

Symptôme Cause Solution
SBOM vide ou incomplet sur un projet Java Syft ne fait pas le deep scan Java par défaut Compléter avec cdxgen –deep, fusionner les SBOM
Composants OS absents du SBOM image Scope par défaut squashed sans --scope all-layers Toujours utiliser --scope all-layers en CI
Trivy ne trouve pas les CVE attendues Base de données vuln pas à jour Forcer trivy --download-db-only avant scan ; pinner version >= 0.70.0
VEX rejeté par le consommateur Justification non standard Utiliser strictement les valeurs CycloneDX 1.7 normalisées
cosign attach échoue avec annotation conflict SBOM déjà attaché sous une version antérieure Utiliser cosign clean avant le re-attach, ou versionner via tag
SBOM passe le validateur officiel mais cassé en aval Différence entre 1.6 et 1.7 Pinner specVersion: "1.7" et exiger des consommateurs à jour

FAQ

CycloneDX ou SPDX, quel format choisir ? Les deux sont reconnus par le NTIA pour la conformité Executive Order 14028 et par l’ENISA pour le CRA. CycloneDX est plus naturellement orienté sécurité applicative (VEX, vulnérabilités natives, CBOM). SPDX est plus mûr côté conformité licences et historiquement utilisé dans le monde Linux Foundation. Une chaîne mature génère les deux ; CycloneDX 1.7 est le format pivot pour les pipelines modernes.

Le Cyber Resilience Act exige-t-il un format précis ? Non, le CRA reste agnostique sur le format. Il exige que le SBOM existe, soit maintenu pendant la durée de support du produit (5 ans minimum pour la plupart des catégories), et soit fourni à la demande des autorités compétentes. CycloneDX 1.7 et SPDX 2.3 sont tous deux conformes.

Faut-il publier le SBOM publiquement ? La règle pratique : publier les SBOM des images conteneur publiques, restreindre l’accès aux SBOM des produits commerciaux propriétaires aux clients sous contrat. Le champ distribution (TLP) introduit en CycloneDX 1.7 permet de marquer un SBOM TLP:AMBER pour signaler la limitation de partage.

Comment maintenir le SBOM à jour entre deux releases ? Régénérer à chaque build via la CI, attacher la version horodatée à l’image, conserver l’historique pendant la durée de support. Pour les services SaaS qui déploient plusieurs fois par jour, conserver le SBOM de chaque déploiement de production permet une investigation post-mortem fiable.

Peut-on enrichir un SBOM existant avec un VEX externe ? Oui, le format VEX peut vivre dans un fichier séparé qui référence le SBOM via bom-ref. Cette séparation est utile quand l’éditeur publie un SBOM stable et émet régulièrement des analyses VEX pour les CVE découvertes après publication.

Tutoriels associés

Lectures recommandées

Sponsoriser ce contenu

Cet emplacement est à vous

Position premium en fin d'article — c'est l'instant où les lecteurs sont le plus engagés. Réservez cet espace pour votre marque, votre formation ou votre offre.

Recevoir nos tarifs
Publicité