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
| Composant | Exemples | Risques associés |
|---|---|---|
| Code source | votre code, contributions externes | injection de code malveillant |
| Dépendances | npm, PyPI, Maven, modules Go | vulnérabilités, typosquattage, compte compromis |
| Outils de construction | compilateurs, assembleurs, chaîne CI/CD | compromission du processus de construction |
| Artefacts | images, binaires, paquets | altération, substitution |
| Infrastructure | registres, réseaux de diffusion, serveurs | interception, 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.
| Attaque | Mé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
| Pilier | Question | Réponse technique |
|---|---|---|
| Transparence | qu'est-ce qui compose mon logiciel ? | le SBOM |
| Intégrité | mon logiciel a-t-il été modifié ? | signatures, SLSA |
| Provenance | d'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.
| Question | Sans SBOM | Avec 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 projets | export filtré instantané |
| quelles licences sont présentes ? | analyse juridique coûteuse | liste générée automatiquement |
Sans inventaire, vous êtes aveugle au moment précis où il faudrait voir.
Deux formats
| Format | Origine | Forces | Cas d'usage |
|---|---|---|---|
| CycloneDX | OWASP | métadonnées de sécurité riches, VEX intégré | réaction aux vulnérabilités |
| SPDX | Linux Foundation | standard ISO, centré sur les licences | conformité 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.jsonGé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.jsonSLSA : 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 ?
| Niveau | Exigences | Ce que cela prouve | Effort |
|---|---|---|---|
| SLSA 0 | aucune | aucune garantie formelle | — |
| SLSA 1 | provenance générée et distribuable | la construction est documentée et traçable | faible |
| SLSA 2 | provenance signée, construction sur plateforme hébergée | le processus n'a pas été altéré après coup | moyen |
| SLSA 3 | construction isolée, secrets de signature inaccessibles aux étapes utilisateur | mê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.
| Composant | Rôle |
|---|---|
| Cosign | l'outil en ligne de commande pour signer et vérifier |
| Fulcio | l'autorité qui délivre les certificats éphémères |
| Rekor | le journal de transparence, public et immuable |
| Gitsign | la 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.0La 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 ciVé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.
Réponse unique
À quoi sert principalement un SBOM ?
Indice · Un SBOM est une nomenclature. Que permet un inventaire ?
[ METTRE EN PRATIQUE ]
Produire et exploiter un SBOM
3 étapes · 30 min · 130 XP
[ CETTE LEÇON DANS LES PARCOURS ]
- Cybersécuritéétape 9 / 13suivant — Sécuriser une pipeline →