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.json

Ouvrez 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ée

L'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

  1. Pas de lockfile : un projet Python avec un simple requirements.txt sans versions figées ne peut pas être inventorié précisément. Figez les versions (pip freeze, poetry.lock, uv.lock).
  2. 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.
  3. Les fichiers de test : Syft catalogue aussi les lockfiles de fixtures ou d'exemples. Excluez-les (--exclude './tests/**') pour ne pas gonfler l'inventaire.
  4. 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.
  5. 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.

À lire ensuite