CaenHackYouAcademy
DevSecOps

Chaîne d'approvisionnement logicielle

SBOM, SLSA, Sigstore : prouver ce que l'on livre.

En décembre 2021, Log4Shell a exposé une réalité inconfortable : la plupart des organisations ne savaient pas si elles utilisaient Log4j. La bibliothèque était présente dans des milliers d'applications, souvent comme dépendance transitive invisible. Les équipes ont passé des semaines à auditer manuellement leurs systèmes pendant que les attaquants exploitaient la faille. La crise a révélé un problème structurel : nous ne savons pas ce qui compose nos logiciels.

Chaîne d'approvisionnement logicielle

L'ensemble des fournisseurs, outils et processus qui interviennent entre votre première ligne de code et l'application déployée. Chaque maillon peut être compromis, et une seule faille suffit à contaminer l'ensemble.

Les maillons de la chaîne

ComposantExemplesRisques associés
Code sourcevotre code, contributions externesinjection de code malveillant
Dépendancesnpm, PyPI, Maven, modules Govulnérabilités, typosquattage, compte compromis
Outils de constructioncompilateurs, assembleurs, chaîne CI/CDcompromission du processus de construction
Artefactsimages, binaires, paquetsaltération, substitution
Infrastructureregistres, réseaux de diffusion, serveursinterception, compromission

Chaque ligne est un point d'entrée potentiel.

L'ampleur du problème

Plus de 80 % du code d'une application moderne provient de dépendances tierces, un ratio stable depuis plusieurs années. En 2025, plus de 454 000 nouveaux paquets malveillants ont été recensés sur les registres publics, portant le total détecté à plus de 1,2 million, dont plus de 99 % sur npm. Une application Node.js moderne compte couramment plusieurs centaines de dépendances une fois l'arbre transitif déplié.

À retenir

Quand vous écrivez une application de 10 000 lignes, vous faites en réalité confiance à 40 000 lignes écrites par des inconnus. Si l'un de ces auteurs voit son compte compromis, votre application peut devenir un vecteur d'attaque — souvent sans que personne ne s'en aperçoive pendant des mois.

AttaqueMécanisme
SolarWinds (2020)code malveillant injecté dans le processus de construction 18 000 organisations compromises
ua-parser-js (2021)compte de publication compromis, mineur de cryptomonnaie injecté dans un paquet téléchargé des millions de fois par semaine
xz utils (2024)porte dérobée implantée après plus de deux ans d'ingénierie sociale sur un mainteneur, découverte par hasard
Polyfill.io (2024)domaine racheté, code malveillant distribué à des centaines de milliers de sites
Shai-Hulud (2025-2026)ver auto-répliquant volant des jetons de publication pour republier des versions infectées plus de 500 versions de paquets touchées

L'OWASP Top 10:2025 place les échecs de la chaîne d'approvisionnement à la troisième place, avec le taux d'incidence le plus élevé de toutes les catégories.

Trois piliers, trois questions

PilierQuestionRéponse technique
Transparencequ'est-ce qui compose mon logiciel ?le SBOM
Intégritémon logiciel a-t-il été modifié ?signatures, SLSA
Provenanced'où vient mon logiciel ?attestations, journaux de transparence

Trois réflexes : sauriez-vous répondre en moins de dix minutes à chacune de ces questions ?

Les trois piliers sont indissociables

Un SBOM sans signature peut être falsifié. Une signature sans SBOM ne dit pas si la dépendance vulnérable est présente. Une attestation de provenance sans les deux ne prouve rien sur le contenu réel de l'artefact. C'est leur intersection qui crée la sécurité.

Le SBOM : l'inventaire des composants

Un SBOM (Software Bill of Materials) est la liste des ingrédients de votre logiciel : les dépendances directes, celles que vous avez explicitement ajoutées les dépendances transitives, celles utilisées par vos dépendances les versions exactes — pas « lodash 4.x » mais « lodash 4.17.21 » les licences et les empreintes cryptographiques.

QuestionSans SBOMAvec SBOM
suis-je affecté par cette CVE ?« il faut vérifier »une requête, une réponse
quelles applications utilisent OpenSSL < 3.0 ?audit manuel de tous les projetsexport filtré instantané
quelles licences sont présentes ?analyse juridique coûteuseliste générée automatiquement

Sans inventaire, vous êtes aveugle au moment précis où il faudrait voir.

Deux formats

FormatOrigineForcesCas d'usage
CycloneDXOWASPmétadonnées de sécurité riches, VEX intégréréaction aux vulnérabilités
SPDXLinux Foundationstandard ISO, centré sur les licencesconformité juridique

Priorité à la sécurité : CycloneDX. Priorité à la conformité : SPDX. Les outils modernes gèrent les deux.

{Un extrait de SBOM CycloneDX : un composant, sa version, son identifiant universel, sa licence.}
{
  "bomFormat": "CycloneDX",
  "specVersion": "1.6",
  "components": [
    {
      "type": "library",
      "name": "lodash",
      "version": "4.17.21",
      "purl": "pkg:npm/lodash@4.17.21",
      "licenses": [{ "license": { "id": "MIT" }}]
    }
  ]
}

Générer et automatiser

{Trois façons de produire un inventaire, selon l'outillage déjà en place.}
# Syft : le plus polyvalent, des dizaines d'écosystèmes
syft packages dir:. -o cyclonedx-json > sbom.json

# Trivy : génération et scan de vulnérabilités dans le même outil
trivy fs --format cyclonedx -o sbom.json .

# Sur une image de conteneur
syft packages registre.example.com/monapp:v1.0.0 -o spdx-json > sbom.json

Générer un SBOM une fois sur son poste ne sert à rien : l'inventaire doit être produit à chaque construction, sinon il devient obsolète dès la première dépendance modifiée.

{Génération et archivage automatiques, avec permissions minimales.}
name: Generate SBOM
on:
  push:
    branches: [main]

permissions: {}

jobs:
  sbom:
    runs-on: ubuntu-latest
    permissions:
      contents: read
    steps:
      - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
        with:
          persist-credentials: false
      - uses: anchore/sbom-action@e22c389904149dbc22b58101806040fa8d37a610 # v0.24.0
        with:
          format: cyclonedx-json
          output-file: sbom.json
      - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
        with:
          name: sbom
          path: sbom.json

SLSA : un cadre de maturité

Les niveaux ci-dessous sont ceux du Build track, celui qui porte sur la construction. La spécification, dans sa version 1.2 approuvée en novembre 2025, a promu un second parcours, le Source track, qui porte sur l'intégrité du dépôt lui-même --- conservation de l'historique et protection continue contre la falsification.

SLSA (Supply-chain Levels for Software Artifacts) définit des niveaux de sécurité progressifs pour la chaîne de construction. Depuis la version 1.0, le volet historique consacré aux sources a été retiré : il ne reste que le track Build, quatre niveaux mesurables de 0 à 3, qui répondent à une seule question — peut-on faire confiance à cet artefact ?

NiveauExigencesCe que cela prouveEffort
SLSA 0aucuneaucune garantie formelle
SLSA 1provenance générée et distribuablela construction est documentée et traçablefaible
SLSA 2provenance signée, construction sur plateforme hébergéele processus n'a pas été altéré après coupmoyen
SLSA 3construction isolée, secrets de signature inaccessibles aux étapes utilisateurmême un accès privilégié au runner ne permet pas de falsifier la provenanceélevé

Viser directement le niveau 3 est irréaliste : le niveau 2 est le bon compromis de départ.

{Une attestation de provenance : quoi, d'où, comment, quand.}
{
  "_type": "https://in-toto.io/Statement/v1",
  "subject": [{ "name": "ghcr.io/monorg/monapp",
                "digest": { "sha256": "abc123..." } }],
  "predicateType": "https://slsa.dev/provenance/v1",
  "predicate": {
    "buildDefinition": {
      "externalParameters": {
        "source": { "uri": "git+https://github.com/monorg/monapp@refs/heads/main",
                    "digest": { "sha1": "def456..." } }
      }
    },
    "runDetails": {
      "metadata": { "invocationId": ".../actions/runs/123456789" }
    }
  }
}

Atteindre le niveau 3 ne demande pas de réécrire le pipeline : il suffit de déléguer la génération de la provenance à un générateur réutilisable, séparé du job de construction. C'est ce découplage qui garantit qu'un attaquant ayant compromis la construction ne peut pas falsifier l'attestation, puisqu'il n'a jamais accès au secret de signature.

Sigstore : signer sans gérer de clés

Le problème historique

Imaginez que pour prouver votre identité, vous deviez porter en permanence un coffre-fort contenant votre passeport : accessible en permanence, et pourtant inviolable. C'est impossible — et c'était exactement le problème de la signature logicielle. Générer une paire de clés, stocker la clé privée de façon sûre, distribuer la clé publique de manière vérifiable, faire tourner les clés, révoquer celles qui fuitent : la grande majorité des projets ne signait rien, parce que c'était trop complexe, trop cher, trop risqué.

L'approche sans clé

Sigstore s'appuie sur des certificats éphémères liés à une identité OIDC.

Le certificat expire au bout de dix minutes, mais la signature reste vérifiable pour toujours.

Le certificat expire, la signature demeure. Si un attaquant compromet votre dépôt, il peut signer une fois pendant dix minutes — mais chaque signature est enregistrée dans un journal public et immuable : l'attaque sera visible.

ComposantRôle
Cosignl'outil en ligne de commande pour signer et vérifier
Fulciol'autorité qui délivre les certificats éphémères
Rekorle journal de transparence, public et immuable
Gitsignla signature des commits Git

Quatre briques depuis octobre 2025, Rekor v2 réduit fortement le coût d'exploitation sans rien changer à l'usage.

{Signature et vérification sans jamais manipuler de clé privée.}
# Signer : ouvre une authentification OIDC
cosign sign ghcr.io/monorg/monapp:v1.0.0

# Vérifier : on contraint l'identité attendue du signataire
cosign verify \
  --certificate-identity "https://github.com/monorg/monrepo/.github/workflows/release.yml@refs/tags/v1.0.0" \
  --certificate-oidc-issuer "https://token.actions.githubusercontent.com" \
  ghcr.io/monorg/monapp:v1.0.0

La publication de confiance

Sigstore ne protège que ce qui est effectivement signé. L'attaque Shai-Hulud a exploité le maillon faible restant : des jetons de publication à longue durée de vie, volés sur des postes ou dans des variables d'environnement. Depuis 2025, npm et PyPI répondent par le Trusted Publishing : au lieu d'un jeton stocké en secret, la chaîne s'authentifie via OIDC directement auprès du registre, qui délivre un jeton éphémère. Le paquet est alors signé automatiquement, avec sa provenance publiée. npm a définitivement désactivé ses anciens jetons en décembre 2025.

Vérifier au moment du déploiement

Signer ne sert à rien si le cluster accepte quand même une image non signée. Un contrôleur d'admission intercepte chaque création de conteneur et peut la refuser.

{Une politique qui refuse toute image non signée.}
apiVersion: policies.kyverno.io/v1
kind: ImageValidatingPolicy
metadata:
  name: verify-signatures
spec:
  validationActions: [Deny]
  matchImageReferences:
    - glob: "ghcr.io/monorg/*"
  attestors:
    - name: cosign-key
      cosign:
        key:
          data: |-
            -----BEGIN PUBLIC KEY-----
            ...
            -----END PUBLIC KEY-----
  validations:
    - expression: "true"
      message: "L'image doit porter une signature Cosign valide."

En production, la vérification sans clé — fondée sur l'identité OIDC du workflow plutôt que sur une clé statique à stocker et faire tourner — est généralement préférable à l'approche par clé montrée ici.

Sécuriser les dépendances

Les dépendances sont le vecteur le plus courant, pour une raison simple : vous ne contrôlez pas leur code, mais vous l'exécutez avec vos propres privilèges.

Épingler : cesser de faire confiance au futur

Écrire "lodash": "\^{}4.17.0", c'est dire au gestionnaire de paquets : « télécharge n'importe quelle version 4.17.x, y compris celles qui n'existent pas encore ». C'est un chèque en blanc. Si le compte du mainteneur est compromis demain, l'attaquant publie une version portant une porte dérobée, et votre prochaine installation la récupérera.

{À gauche le chèque en blanc, à droite la version que vous avez réellement testée.}
// Dangereux
{ "dependencies": { "lodash": "^4.17.0", "express": "*" } }

// Sûr
{ "dependencies": { "lodash": "4.17.21", "express": "4.18.2" } }

Verrouiller : figer l'arbre complet

Épingler ne suffit pas : vos dépendances ont elles-mêmes des dépendances. Vous épinglez la version 4.18.2 d'express, qui dépend de body-parser, qui dépend de iconv-lite, qui dépend de safer-buffer. Si ce dernier publie une version malveillante acceptée par la chaîne, vous la téléchargerez sans avoir jamais entendu son nom. Le fichier de verrouillage fige l'arbre complet : chaque paquet, chaque version, chaque empreinte.

{La différence tient en deux lettres.}
# npm install peut mettre à jour le fichier de verrouillage
# npm ci installe exactement ce qu'il contient, ou echoue
npm ci

Vérifier les empreintes, scanner les vulnérabilités

Même avec un fichier de verrouillage, un attaquant contrôlant le registre pourrait substituer un paquet de même nom et de même version. Les fichiers de verrouillage modernes incluent des empreintes cryptographiques : si le contenu téléchargé ne correspond pas, l'installation échoue.

{Empreintes vérifiées, scripts d'installation désactivés, vulnérabilités scannées.}
# --ignore-scripts : un paquet compromis ne peut plus exfiltrer via post-install
npm ci --ignore-scripts

# Python
pip-compile requirements.in --generate-hashes
pip-sync requirements.txt

# Scanner les vulnerabilites connues
npm audit --audit-level=high
trivy fs --severity HIGH,CRITICAL .

Feuille de route

Quatre paliers

  • Visibilité — générer des SBOM pour les projets critiques, scanner les dépendances en intégration, inventorier les registres et sources.
  • Intégrité — signer les images, vérifier les empreintes, imposer les fichiers de verrouillage, migrer vers la publication de confiance.
  • Provenance — générer des attestations SLSA de niveau 2, vérifier les signatures au déploiement, auditer les workflows.
  • Maturité — viser SLSA 3, centraliser le suivi des composants, automatiser la production de VEX.

À retenir de cette séance

SBOM : savoir ce qui compose vos logiciels, pour répondre aux vulnérabilités en minutes plutôt qu'en semaines. SLSA : un cadre de maturité en quatre niveaux, viser le niveau 2 au minimum. Sigstore : la signature sans clé, il n'y a plus d'excuse pour ne pas signer. La publication de confiance remplace les jetons de longue durée exploités par des attaques comme Shai-Hulud. Dépendances : épingler, verrouiller, scanner, vérifier les empreintes. Et progressivité : la visibilité d'abord, puis l'intégrité, puis la provenance.

VérificationQuestion 1 / 3

Réponse unique

À quoi sert principalement un SBOM ?

Indice · Un SBOM est une nomenclature. Que permet un inventaire ?

On this page