Générer un SBOM dans GitHub Actions et GitLab CI en 10 minutes
Par l'équipe Lysbor · publié le · 3 min de lecture
Un SBOM n'a de valeur que s'il est à jour. La seule façon fiable d'y parvenir : le générer automatiquement à chaque build, dans la CI, au même titre que les tests. Ce tutoriel donne les fichiers prêts à copier pour GitHub Actions et GitLab CI, d'abord avec des outils open source seuls, puis avec l'agent Lysbor pour ajouter la surveillance continue.
Générer le SBOM à la main, c'est comme faire l'inventaire d'un magasin une fois par an. Le générer en CI, c'est la caisse enregistreuse qui met le stock à jour à chaque vente.
Ce dont vous avez besoin
- un dépôt avec un lockfile commité (
package-lock.json,poetry.lock,go.sum,Cargo.lock,composer.lock…) : sans lockfile, les versions exactes ne sont pas connues ; - l'outil open source Syft, d'Anchore, sous licence Apache 2.0, qui sait analyser un dossier comme une image de conteneur ;
- dix minutes.
Étape 1 : essayer en local
Installez Syft depuis ses versions publiées sur GitHub (archives avec sommes de contrôle), puis lancez :
# SBOM du dépôt courant, au format CycloneDX JSON
syft dir:. -o cyclonedx-json=sbom.cdx.json
# SBOM d'une image de conteneur (paquets système compris)
syft registry.example.com/mon-app:1.4.2 -o cyclonedx-json=image.cdx.json
# Les deux formats d'un coup, si un client exige SPDX
syft dir:. -o cyclonedx-json=sbom.cdx.json -o spdx-json=sbom.spdx.jsonOuvrez sbom.cdx.json : vous y trouverez un tableau components, avec pour chaque paquet son nom, sa version et son purl. Si la liste est anormalement courte, vérifiez que le lockfile est bien présent et à la racine analysée.
Étape 2 : GitHub Actions
Créez le fichier .github/workflows/sbom.yml :
name: sbom
on:
push:
branches: [main]
release:
types: [published]
permissions:
contents: read
jobs:
sbom:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Installer Syft
run: |
# remplacez par la version publiée de votre choix, et vérifiez sa somme de contrôle
SYFT_VERSION=1.52.0
curl -sSfL -o syft.tar.gz "https://github.com/anchore/syft/releases/download/v${SYFT_VERSION}/syft_${SYFT_VERSION}_linux_amd64.tar.gz"
tar -xzf syft.tar.gz syft && sudo mv syft /usr/local/bin/
- name: Générer le SBOM
run: syft dir:. -o cyclonedx-json=sbom.cdx.json
- uses: actions/upload-artifact@v4
with:
name: sbom-${{ github.sha }}
path: sbom.cdx.jsonÀ chaque push sur main et à chaque version publiée, le SBOM est généré et conservé comme artefact du workflow. Pour une conservation longue (le Cyber Resilience Act demande de documenter chaque version mise sur le marché), attachez-le aussi à la release ou archivez-le ailleurs, car les artefacts de workflow expirent.
Étape 3 : GitLab CI
Ajoutez à .gitlab-ci.yml :
sbom:
stage: test
image: alpine:3.20
variables:
SYFT_VERSION: "1.52.0"
before_script:
- apk add --no-cache curl tar
- curl -sSfL -o syft.tar.gz "https://github.com/anchore/syft/releases/download/v${SYFT_VERSION}/syft_${SYFT_VERSION}_linux_amd64.tar.gz"
- tar -xzf syft.tar.gz syft && mv syft /usr/local/bin/
script:
- syft dir:. -o cyclonedx-json=sbom.cdx.json
artifacts:
paths: [sbom.cdx.json]
expire_in: 1 year
rules:
- if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
- if: $CI_COMMIT_TAGÉtape 4 : faire surveiller le SBOM
À ce stade, vous avez un inventaire à jour. Mais un SBOM stocké ne prévient personne quand une nouvelle vulnérabilité est publiée demain sur l'un de ses composants. Il faut le confronter chaque jour à une base à jour et être alerté sur ce qui change.
Avec Lysbor, l'agent lysbor-scan fait la génération et l'envoi en une étape. Il installe Syft (et Trivy si besoin) depuis les archives publiées en vérifiant leur empreinte SHA-256, génère le SBOM et l'envoie. Lysbor le confronte ensuite chaque nuit à la base OSV et n'alerte que sur ce qui est nouveau.
GitHub Actions :
jobs:
lysbor:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Installer l'agent Lysbor
run: |
curl -sSfL -o /usr/local/bin/lysbor-scan https://lysbor.com/agent/lysbor-scan.sh && chmod +x /usr/local/bin/lysbor-scan
lysbor-scan install-tools
- name: Inventaire et envoi
env:
LYSBOR_URL: https://lysbor.com
LYSBOR_API_KEY: ${{ secrets.LYSBOR_API_KEY }}
LYSBOR_PROJECT: ${{ vars.LYSBOR_PROJECT }}
run: lysbor-scan --fail-on critical .GitLab CI :
include:
- remote: 'https://lysbor.com/agent/lysbor-gitlab-ci.yml'
variables:
LYSBOR_URL: https://lysbor.com
LYSBOR_PROJECT: <identifiant du projet>
LYSBOR_OPTS: "" # "--all" pour ajouter Semgrep (code) et Trivy (configuration, secrets)
LYSBOR_FAIL_ON: critical
# LYSBOR_API_KEY : Settings > CI/CD > Variables, masquéeL'option --fail-on critical fait échouer le pipeline tant qu'une vulnérabilité critique reste ouverte. Une vulnérabilité que vous avez décidé d'accepter dans l'interface, avec une justification, ne bloque plus : la décision débloque le pipeline sans toucher au code. Le détail des options est sur la page Agent CI lysbor-scan.
Les pièges fréquents
- Pas de lockfile : un projet Python avec un simple
requirements.txtsans versions figées ne peut pas être inventorié précisément. Figez les versions (pip freeze,poetry.lock,uv.lock). - Le SBOM du dépôt au lieu de l'image : pour un service conteneurisé, générez aussi le SBOM de l'image finale. C'est elle qui tourne en production, avec ses paquets système.
- Les fichiers de test : Syft catalogue aussi les lockfiles de fixtures ou d'exemples. Excluez-les (
--exclude './tests/**') pour ne pas gonfler l'inventaire. - Les dépendances de développement : elles ne tournent pas en production, mais un outil de build compromis peut contaminer ce qui est livré. Décidez consciemment de les inclure ou non.
- Un jeton de CI trop puissant : la clé qui envoie le SBOM n'a besoin que des droits d'envoi et de lecture, jamais d'administration.
Questions fréquentes
Quel outil choisir entre Syft, cdxgen et Trivy pour générer un SBOM ?
Les trois produisent du CycloneDX de bonne qualité. Syft est simple et polyvalent (dossiers et images). cdxgen, du projet OWASP CycloneDX, va plus loin sur certains écosystèmes. Trivy génère aussi des SBOM en plus de ses analyses. L'important est d'en choisir un et de l'exécuter à chaque build.
À quelle fréquence générer le SBOM ?
À chaque build de la branche principale et à chaque version publiée. La surveillance des vulnérabilités, elle, doit être quotidienne, même quand le code ne change pas, car de nouvelles vulnérabilités sont publiées chaque jour.
Faut-il commiter le SBOM dans le dépôt ?
Ce n'est pas nécessaire et cela crée du bruit dans l'historique. Conservez-le comme artefact de build, attaché aux versions publiées, ou envoyez-le à un outil de suivi qui l'historise.