SBOM
SBOM Docker : comment en générer une, et ce qu'elle rate
Vous pouvez obtenir une SBOM d'une image Docker en une commande, au build avec BuildKit ou après coup avec Docker Scout ou Syft. Chacun lit les métadonnées de paquets qu'il trouve dans l'image. C'est le bon enregistrement de ce que contient l'image, dans la limite de ces métadonnées. Ce n'est pas un enregistrement de la façon dont l'image a été construite.
Mis à jour le
Comment générer une SBOM pour une image Docker
Il existe trois méthodes courantes. BuildKit peut écrire la SBOM pendant qu'il construit l'image et l'y attacher sous forme d'attestation. Docker Scout et Syft en génèrent une à partir d'une image qui existe déjà, en local ou dans un registre.
Au build, avec BuildKit
Ajoutez --sbom=true, ou sa forme longue --attest type=sbom, à docker buildx build. BuildKit exécute son plugin de scan Syft sur le résultat et attache la SBOM à l'image sous forme de document SPDX JSON. Construisez avec l'exportateur local pour examiner la SBOM avant de pousser quoi que ce soit :
# Build the image, attach an SBOM attestation and push it
docker buildx build --sbom=true -t registry.example.com/app:1.0 --push .
# The long form of the same option
docker buildx build --attest type=sbom -t registry.example.com/app:1.0 --push .
# Check the SBOM before pushing: write the build result to ./out
docker buildx build --sbom=true --output type=local,dest=out .
# out/sbom.spdx.json is the SBOM Lire la SBOM attachée à une image
docker buildx imagetools inspect relit l'attestation depuis le registre. Tout ce qui concerne la SBOM se trouve sous .SBOM dans son template Go :
# Print the SPDX document attached to the image
docker buildx imagetools inspect registry.example.com/app:1.0 \
--format "{{ json .SBOM.SPDX }}"
# List each package and its version
docker buildx imagetools inspect registry.example.com/app:1.0 \
--format "{{ range .SBOM.SPDX.packages }}{{ .name }}@{{ .versionInfo }}{{ println }}{{ end }}" À partir d'une image existante, avec Docker Scout
docker scout sbom utilise l'attestation SBOM de l'image lorsqu'elle existe. Sinon, il indexe lui-même le contenu de l'image. Il affiche du JSON par défaut et écrit dans un fichier avec --output :
# List the packages in an image
docker scout sbom --format list registry.example.com/app:1.0
# Write an SPDX or CycloneDX SBOM to a file
docker scout sbom --format spdx --output app.spdx.json registry.example.com/app:1.0
docker scout sbom --format cyclonedx --output app.cdx.json registry.example.com/app:1.0 À partir d'une image existante, avec Syft
Syft est le scanner open source sur lequel repose le plugin de BuildKit. Pointez-le vers une image et choisissez le format avec -o. Ajoutez =file pour écrire chaque format dans son propre fichier :
# CycloneDX JSON to the terminal
syft registry.example.com/app:1.0 -o cyclonedx-json
# Both formats, each to its own file
syft registry.example.com/app:1.0 -o spdx-json=app.spdx.json -o cyclonedx-json=app.cdx.json SPDX ou CycloneDX ?
Les attestations BuildKit sont toujours en SPDX. Docker Scout écrit en SPDX ou CycloneDX, et Syft écrit les deux, entre autres formats. Les deux normes listent les paquets, les versions, les licences et les package URLs : le choix dépend donc généralement de l'outil qui lira ensuite la SBOM. Voir CycloneDX vs SPDX pour les différences.
Comment un scanner d'images construit une SBOM
Tous ces outils fonctionnent de la même façon. Ils décompressent les couches de l'image et lisent les métadonnées de paquets qu'ils trouvent : la base de données de paquets du système d'exploitation et les métadonnées laissées par les gestionnaires de paquets des langages. Chaque paquet qu'ils peuvent identifier devient une entrée de la SBOM, y compris les paquets issus de l'image de base.
Inclure les étapes de build et le contexte de build
Par défaut, BuildKit ne scanne que l'étape finale. Dans un build multi-étapes, les compilateurs, outils de build et paquets utilisés aux étapes précédentes ne sont pas dans l'image finale : ils ne sont donc pas non plus dans sa SBOM. La documentation Docker sur les attestations SBOM décrit deux arguments de build qui élargissent le scan. BUILDKIT_SBOM_SCAN_STAGE ajoute une étape, et BUILDKIT_SBOM_SCAN_CONTEXT ajoute le contexte de build :
# syntax=docker/dockerfile:1
# Scan the build context as well as the image
ARG BUILDKIT_SBOM_SCAN_CONTEXT=true
FROM golang:1.25 AS build
# Include this build stage in the SBOM
ARG BUILDKIT_SBOM_SCAN_STAGE=true
WORKDIR /src
COPY . .
RUN go build -o /out/app .
FROM scratch
COPY --from=build /out/app /app
ENTRYPOINT ["/app"] Tous deux doivent être déclarés avec ARG dans le Dockerfile. Les définir uniquement avec --build-arg n'a aucun effet, même si --build-arg peut remplacer une valeur déclarée par le Dockerfile. Avec l'exportateur local, chaque étape scannée obtient son propre fichier, comme sbom-build.spdx.json à côté de sbom.spdx.json.
Ce qu'un scan rate encore
Le scan des étapes comble une lacune. Mais le scanner lit toujours des fichiers, et une partie de ce qu'utilise un build ne laisse aucun fichier, ou aucun qu'il puisse identifier :
- Les fichiers sans métadonnées de paquet. Un binaire téléchargé avec
curl, une archive décompressée dans une étapeRUNou du code vendoré copié dans l'image. Certains binaires, comme les binaires Go, portent des informations de build lisibles par un scanner ; beaucoup n'en portent pas. - Ce que le build a téléchargé puis supprimé. Un paquet ou un installateur qu'une étape
RUNrécupère, utilise et retire dans la même couche ne laisse sur le système de fichiers rien qu'un scanner puisse lire, à l'étape finale ou non. - Comment les éléments sont entrés. Une SBOM issue d'un scan liste ce qui est là. Elle ne dit pas de quel registre ou de quel hôte provient un paquet, ni quelle étape l'a récupéré.
- Les étapes que vous n'avez pas marquées. Le scan des étapes est à activer, par étape ou globalement. Une étape sans l'argument reste exclue.
- Les réglages du scan. Ce qui apparaît dépend de la façon dont le scanner est lancé. Sur un projet, un seul flag Syft décide si les paquets npm apparaissent ou non dans le résultat.
Pourquoi c'est important
Un outil de build ou une image de base compromis affecte ce que vous livrez, même s'il n'apparaît jamais dans l'image finale. Et un binaire sans métadonnées peut contenir une vulnérabilité vers laquelle aucune entrée de SBOM ne pointe. Lorsqu'un avis de sécurité tombe, vous devez savoir ce qui a servi à construire l'image autant que ce qu'elle contient.
Enregistrez aussi le build
La SBOM d'image répond à la question de ce qui se trouve dans l'image. Un enregistrement du build répond à la question de ce que le build a récupéré : les images de base qu'il a tirées et les paquets récupérés par chaque étape, y compris les dépendances cachées qu'aucun lockfile ne liste. CRACI enregistre cela pendant l'exécution de votre job GitHub Actions, via un proxy qui comprend les paquets sur le runner, et l'API renvoie les SBOM, les traces réseau et la provenance du job. Utilisez la SBOM d'image pour ce que vous livrez et l'enregistrement du build pour la façon dont cela a été fait.
Voir le comparatif des outils SBOM, les SBOM au build et comment générer une SBOM dans GitHub Actions.
SBOM Docker : questions fréquentes
Comment générer une SBOM pour une image Docker ?
Il existe trois méthodes courantes. Ajoutez --sbom=true à docker buildx build et BuildKit attache une SBOM SPDX à l'image. Exécutez docker scout sbom sur une image existante. Ou exécutez Syft, par exemple syft IMAGE -o cyclonedx-json. Toutes les trois lisent les paquets trouvés dans l'image.
Qu'est-ce qu'un scanner SBOM ?
Un outil qui lit des fichiers, comme un répertoire source, un lockfile ou une image de conteneur, et écrit une SBOM des paquets qu'il peut identifier. Syft, Trivy, Docker Scout et le plugin Syft de BuildKit sont des scanners SBOM. Ils décrivent les fichiers qu'ils ont devant eux, pas le build qui les a produits.
Quel format de SBOM Docker produit-il ?
Les attestations BuildKit sont des documents SPDX JSON attachés à l'image. Docker Scout peut afficher une liste de paquets ou écrire en SPDX ou CycloneDX. Syft écrit les deux, et d'autres encore. Choisissez le format qu'attend l'outil qui consomme la SBOM.
Comment un scanner construit-il une SBOM à partir d'une image Docker ?
Il décompresse les couches de l'image et lit les métadonnées de paquets qu'il trouve : la base de données de paquets du système d'exploitation et les fichiers de paquets des langages, comme les métadonnées des paquets npm ou Python installés. Chaque paquet qu'il peut identifier devient une entrée de la SBOM.
Pourquoi une SBOM d'image raterait-elle un composant ?
Parce qu'elle ne peut lister que ce qu'elle peut identifier dans les fichiers qu'elle lit. Un binaire téléchargé avec curl ne porte aucune métadonnée de paquet, un paquet téléchargé puis supprimé par une étape de build ne laisse rien à lire, et les étapes de build précédentes sont exclues sauf si vous activez le scan des étapes.
Une SBOM d'image reste-t-elle utile ?
Oui. C'est le bon enregistrement de ce que contient l'image que vous livrez, y compris les paquets issus de l'image de base. Simplement, elle ne décrit pas la façon dont l'image a été construite : associez-la à un enregistrement du build lorsque cela compte.
Voyez ce que le build de votre image a récupéré
Exécutez un build d'image sur CRACI et comparez son enregistrement des images de base et paquets récupérés à la SBOM d'image de votre scanner.
Réserver une démo