Accueil

Supply Chain Security : SBOM, SCA et Hardening CI/CD

Security
Difficulte: Advanced
20 min de lecture

Apprenez à sécuriser votre chaîne logicielle de bout en bout : générez des SBOM avec Syft, scannez les dépendances avec Trivy et Grype, durcissez vos pipelines GitHub Actions et GitLab CI, signez vos artefacts avec Cosign et atteignez les niveaux SLSA.

Retour aux tutoriels

L'essentiel

  • Un SBOM répond en quelques secondes à la question qui a coûté des semaines pendant Log4Shell : « utilisons-nous ce composant ? ». syft image:my-app:latest -o cyclonedx-json=sbom.cdx.json le génère à chaque build. Choix du format : CycloneDX (OWASP, orienté sécurité, porte nativement les VEX) pour l'opérationnel, SPDX (ISO 5962:2021, Linux Foundation) pour la conformité de licences — Syft produit les deux.
  • Côté SCA, les trois scanners ne se recouvrent pas : Trivy couvre images, système de fichiers, dépôts Git, IaC et secrets — c'est le couteau suisse CI ; Grype vise la précision maximale sur les dépendances et lit directement un SBOM (grype sbom:sbom.cdx.json) ; OWASP Dependency-Check fait l'audit fin du code source mais reste lent (API NVD). La commande qui bloque un pipeline : trivy image --severity HIGH,CRITICAL --exit-code 1 my-app:latest.
  • Trois durcissements non négociables pour GitHub Actions : épingler chaque action par hash SHA et non par tag (actions/checkout@b4ffde65...), car un tag v4 peut être réassigné vers un commit malveillant — pinact run automatise la conversion ; déclarer permissions: contents: read par défaut et n'ouvrir packages: write ou id-token: write qu'au job qui en a besoin ; ne jamais interpoler ${{ github.event.pull_request.title }} dans un run: — passer par une variable d'environnement, sinon l'injection de commande est triviale.
  • Le mode keyless de Cosign supprime le problème de la clé privée à stocker : l'identité provient du token OIDC du job CI. Signer coûte une ligne (cosign sign --yes $IMAGE@$DIGEST), et la vérification côté consommateur porte sur l'identité du workflow avec cosign verify --certificate-identity "https://github.com/org/repo/.github/workflows/release.yml@refs/heads/main" --certificate-oidc-issuer "https://token.actions.githubusercontent.com".
  • Le framework SLSA chiffre l'effort : niveau 1 (build scripté, provenance non signée) en quelques heures, niveau 2 (service de build hébergé, provenance signée via slsa-github-generator) en 1-2 jours, niveau 3 (isolation forte des builds) en semaines, niveau 4 (revue à deux parties) en mois. La plupart des projets s'arrêtent au niveau 2-3, meilleur ratio sécurité/effort.
Contexte de menace réel
SolarWinds (2020), Codecov (2021), Log4Shell (2021), XZ Utils (2024) : les attaques ciblant la chaîne d'approvisionnement logicielle sont devenues le vecteur d'attaque le plus dévastateur. Un seul composant compromis peut affecter des milliers d'organisations simultanément.

Pourquoi la supply chain logicielle est la cible prioritaire

En décembre 2020, des attaquants ont compromis les systèmes de build de SolarWinds et inséré une backdoor dans les mises à jour légitimes de la suite Orion. Plus de 18 000 organisations ont téléchargé la mise à jour empoisonnée, dont des agences gouvernementales américaines. L'attaque est restée indétectée pendant 9 mois.

En décembre 2021, la CVE-2021-44228 (Log4Shell) a révélé une vulnérabilité critique dans Log4j, une bibliothèque Java utilisée dans des centaines de milliers d'applications. Le problème : la plupart des équipes ne savaient même pas qu'elles utilisaient Log4j — elle était présente en tant que dépendance transitive, cachée plusieurs niveaux en profondeur.

Ces deux incidents illustrent les deux vecteurs principaux des attaques supply chain :

  • Compromission de la chaîne de build : un attaquant altère le processus de compilation ou les outils de build
  • Vulnérabilités dans les dépendances : des bibliothèques tierces contiennent des failles inconnues ou volontairement introduites

Ce tutoriel couvre les quatre piliers défensifs : inventaire (SBOM), détection (SCA), durcissement du pipeline (CI/CD) et vérification des artefacts (signature + provenance).

SBOM : Software Bill of Materials

Un SBOM est l'équivalent logiciel de la liste des ingrédients d'un produit alimentaire. Il liste exhaustivement tous les composants d'une application : bibliothèques directes, dépendances transitives, versions exactes, licences et relations entre composants.

CycloneDX vs SPDX : choisir son format

Deux standards dominent le marché :

  • SPDX (Software Package Data Exchange) — Standard ISO 5962:2021, maintenu par la Linux Foundation. Orienté conformité de licences. Format XML, JSON ou RDF. Recommandé pour les analyses légales et la distribution open source.
  • CycloneDX — Standard OWASP, orienté sécurité. Supporte les SBOM, HBOM (hardware), MBOM (modèles ML) et les documents VEX. Format JSON, XML ou Protocol Buffers. Recommandé pour les usages DevSecOps.
Recommandation
Utilisez CycloneDX pour la sécurité opérationnelle (CVE tracking, VEX) et SPDX si votre équipe légale a besoin d'analyses de conformité de licences. Les deux formats sont interopérables et Syft génère les deux.

Générer un SBOM avec Syft

Syft (Anchore) est l'outil de référence pour générer des SBOM depuis des images Docker, des répertoires de code source ou des archives.

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

# Vérifier l'installation
syft version

# Générer un SBOM depuis une image Docker (format CycloneDX JSON)
syft image:my-app:latest -o cyclonedx-json=sbom.cdx.json

# Générer un SBOM depuis une image avec tag complet
syft registry:myregistry.io/my-app:v1.2.3 -o cyclonedx-json=sbom.cdx.json

# Générer depuis un répertoire (analyse le code source)
syft dir:/path/to/project -o cyclonedx-json=sbom.cdx.json

# Format SPDX JSON
syft image:my-app:latest -o spdx-json=sbom.spdx.json

# Format SPDX tag-value (pour les toolchains légaux)
syft image:my-app:latest -o spdx-tag-value=sbom.spdx

# Affichage en tableau pour inspection rapide
syft image:my-app:latest -o table

# Inclure les paquets de dev dans le SBOM
syft dir:/project -o cyclonedx-json --scope all-layers

Un SBOM CycloneDX JSON ressemble à ceci (extrait simplifié) :

{
  "bomFormat": "CycloneDX",
  "specVersion": "1.6",
  "serialNumber": "urn:uuid:3e671687-395b-41f5-a30f-a58921a69b79",
  "version": 1,
  "metadata": {
    "timestamp": "2026-02-20T10:00:00Z",
    "tools": [{"vendor": "anchore", "name": "syft", "version": "1.4.0"}],
    "component": {
      "type": "container",
      "name": "my-app",
      "version": "1.2.3"
    }
  },
  "components": [
    {
      "type": "library",
      "name": "log4j-core",
      "version": "2.17.1",
      "purl": "pkg:maven/org.apache.logging.log4j/[email protected]",
      "licenses": [{"expression": "Apache-2.0"}]
    }
  ]
}

Intégration du SBOM dans votre pipeline CI

Le SBOM doit être généré à chaque build et archivé comme artefact. Voici un exemple GitHub Actions :

# .github/workflows/sbom.yml
name: SBOM Generation

on:
  push:
    branches: [main]
  release:
    types: [published]

jobs:
  sbom:
    runs-on: ubuntu-latest
    permissions:
      contents: write
      packages: read

    steps:
      - name: Checkout
        uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11  # v4.1.1

      - name: Build image
        run: docker build -t my-app:${{ github.sha }} .

      - name: Install Syft
        uses: anchore/sbom-action/download-syft@fd74a6fb98a204a1ad35bbfae0122c1a302ff88d  # v0.15.0

      - name: Generate SBOM
        uses: anchore/sbom-action@fd74a6fb98a204a1ad35bbfae0122c1a302ff88d  # v0.15.0
        with:
          image: my-app:${{ github.sha }}
          format: cyclonedx-json
          output-file: sbom-${{ github.sha }}.cdx.json
          artifact-name: sbom-${{ github.sha }}.cdx.json

      - name: Upload SBOM as release asset
        if: github.event_name == 'release'
        uses: actions/upload-release-asset@e8f9f06c4b078e705bd2ea027f0926603fc9b4d5  # v1.0.2
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        with:
          upload_url: ${{ github.event.release.upload_url }}
          asset_path: sbom-${{ github.sha }}.cdx.json
          asset_name: sbom.cdx.json
          asset_content_type: application/json

Contenu Premium

Ce tutoriel avancé est réservé aux membres premium.

9,90€ / mois
  • Tous les tutoriels avancés
  • Nouveaux contenus chaque semaine
  • Suivi de progression
  • Annulation à tout moment
MR

Écrit par

Morgann Riu

Expert en cybersécurité et administration Linux. Je partage mes connaissances à travers des tutoriels gratuits et des formations pour aider les administrateurs systèmes et développeurs à sécuriser leurs infrastructures.

Questions fréquentes

Qu'est-ce qu'un SBOM et pourquoi est-il obligatoire ?
Un SBOM (Software Bill of Materials) est un inventaire exhaustif de tous les composants logiciels d'une application : bibliothèques, dépendances transitives, versions et licences. Il est rendu obligatoire par le décret exécutif américain de 2021 sur la cybersécurité pour les logiciels vendus au gouvernement fédéral américain, et fortement recommandé par l'ENISA en Europe. Il permet de répondre immédiatement à la question "sommes-nous vulnérables ?" lors de la publication d'une nouvelle CVE comme Log4Shell.
Quelle est la différence entre CycloneDX et SPDX ?
SPDX (Software Package Data Exchange) est un standard ISO (ISO 5962:2021) principalement orienté conformité de licences, maintenu par la Linux Foundation. CycloneDX est un standard OWASP spécialement conçu pour la sécurité, supportant les SBOM mais aussi les HBOM (hardware), MBOM (machine learning) et les VEX (Vulnerability Exploitability eXchange). Pour la sécurité opérationnelle, CycloneDX est préférable car il intègre nativement les données de vulnérabilités. SPDX est préférable pour les analyses de licences et la conformité légale.
Quelle différence entre Trivy, Grype et OWASP Dependency-Check ?
Trivy (Aqua Security) est le scanner le plus polyvalent : images Docker, fichiers système, repos Git, configurations IaC. Il est rapide, facile à intégrer en CI et supporte de nombreux formats. Grype (Anchore) se concentre sur les images et systèmes de fichiers avec une excellente précision et le format SARIF pour GitHub Security. OWASP Dependency-Check analyse spécifiquement les dépendances de code source (Maven, npm, NuGet, pip) et intègre la base NVD. En pratique, Trivy couvre 90% des besoins, complété par Dependency-Check pour l'analyse fine des dépendances applicatives.
Qu'est-ce que SLSA et comment progresser entre les niveaux ?
SLSA (Supply-chain Levels for Software Artifacts) est un framework de sécurité de Google structuré en 4 niveaux. Niveau 1 : le build est scripté et produit une provenance (automatisable en quelques heures). Niveau 2 : utilisation d'un service de build hébergé avec provenance signée (GitHub Actions + slsa-github-generator). Niveau 3 : le service de build est durci et la provenance prouve une isolation forte. Niveau 4 : processus entièrement vérifiable avec deux parties de revue. La plupart des projets open source visent le niveau 2-3 comme bon équilibre sécurité/effort.
Comment gérer les faux positifs dans les scans SCA ?
Les faux positifs sont inévitables. Pour les gérer, utilisez les fichiers .trivyignore ou .grype.yaml pour ignorer des CVE spécifiques avec une justification documentée. Créez des documents VEX (Vulnerability Exploitability eXchange) au format CycloneDX qui déclarent officiellement pourquoi une CVE n'est pas exploitable dans votre contexte (composant non appelé, mitigations en place). Définissez une politique claire : seules les CVE CRITICAL sans workaround bloquent le pipeline, les HIGH nécessitent un ticket de suivi sous 30 jours. Revoyez les exceptions trimestriellement.
Comment configurer Dependabot pour des mises à jour automatiques de sécurité ?
Ajoutez un fichier .github/dependabot.yml à la racine de votre dépôt. Configurez-y chaque écosystème (npm, pip, docker, github-actions) avec une fréquence (daily/weekly), un préfixe de branche, et des labels. Activez les security updates en plus des version updates. Pour les monorepos, déclarez chaque répertoire séparément. Combinez Dependabot avec les branch protection rules pour exiger des reviewers sur les PRs Dependabot et éviter les mises à jour automatiques en production.

Partager ce tutoriel

Cet article vous a plu ?

Cet article vous a-t-il été utile ?

Merci pour votre retour !

Commentaires

Recommandé pour vous

Article de fond sur le sujet

Checklist Sécurité Linux

30 points essentiels pour sécuriser un serveur Linux. Recevez aussi les nouveaux tutoriels par email.

Pas de spam. Désabonnement en 1 clic.