En décembre 2021, la faille Log4Shell a posé une question à laquelle la plupart des équipes ne savaient pas répondre : « utilisons-nous Log4j, et où ? ». La supply chain logicielle, tout ce qui intervient entre une ligne de code et l'application en production, est devenue la cible privilégiée des attaquants : en 2025, Sonatype a recensé plus de 454 600 nouveaux paquets malveillants. Cette leçon ouvre le module sur la chaîne d'approvisionnement : elle donne la carte des risques et des trois réponses, SBOM, SLSA et Sigstore, que les leçons suivantes détaillent une à une.
Les commandes d'installation de dépendances sont mesurées : npm ci
refuse un lock falsifié, pip refuse un paquet dont l'empreinte ne
correspond pas, et une application Express d'une seule dépendance en tire 69
autres.
Ce que vous allez apprendre
Section intitulée « Ce que vous allez apprendre »- Situer les maillons de la chaîne et les attaques qui les ont visés
- Distinguer les trois questions : transparence, intégrité, provenance
- Produire un SBOM et lire ce qu'il contient
- Situer un build sur les niveaux de SLSA 1.2
- Expliquer la signature sans clé de Sigstore et le Trusted Publishing
- Durcir l'installation des dépendances avec un lock, des empreintes et
--ignore-scripts
Qu'est-ce que la supply chain logicielle ?
Section intitulée « Qu'est-ce que la supply chain logicielle ? »La supply chain logicielle est l'ensemble des fournisseurs, outils et processus qui interviennent entre votre première ligne de code et l'application déployée. Le mot vient de la logistique, et l'analogie tient : un produit n'est pas plus sûr que la pièce la moins contrôlée qui le compose. Chaque maillon est un point d'entrée possible.
| Maillon | Exemples | Ce qu'un attaquant y fait |
|---|---|---|
| Code source | votre dépôt, les contributions externes | injecte du code par un compte ou une revue faible |
| Dépendances | npm, PyPI, Maven, modules Go | publie une version piégée ou un nom proche (typosquatting) |
| Build | runners CI, compilateurs, actions | modifie l'artefact pendant sa fabrication |
| Artefacts | images, binaires, paquets | substitue un artefact par un autre au même nom |
| Distribution | registres, CDN | sert une version altérée à tous les clients |
Combien de code vient d'ailleurs ?
Section intitulée « Combien de code vient d'ailleurs ? »D'après le rapport OSSRA 2026 de Black Duck, 98 % des applications commerciales auditées contiennent de l'open source, qui représente en moyenne 70 % de leur code. Le chiffre se vérifie en une commande : une application qui ne déclare qu'Express en dépendance installe 69 paquets, mesuré avec npm 11.19.0.
$ cat package.json{ "name": "demo-sbom", "version": "1.0.0", "dependencies": { "express": "4.21.2" } }$ npm install --silent$ node -e 'const l=require("./package-lock.json"); console.log(Object.keys(l.packages).length - 1)'69Chacun de ces 69 paquets a un ou plusieurs mainteneurs dont vous n'avez jamais vérifié la sécurité du compte. Le rapport 2026 de Sonatype donne l'autre face du problème : 454 600 paquets malveillants publiés en 2025, 1,233 million au total, et plus de 99 % de ce malware sur npm.
Cinq attaques qui ont changé les pratiques
Section intitulée « Cinq attaques qui ont changé les pratiques »Chaque attaque marquante a visé un maillon différent, et chacune a laissé une parade derrière elle. Les retenir par paire, attaque et parade, est le moyen le plus sûr de comprendre à quoi sert chaque outil du module.
| Attaque | Maillon visé | Ce qui s'est passé | Parade apparue ensuite |
|---|---|---|---|
| SolarWinds (2020) | build | du code malveillant inséré pendant la compilation d'Orion ; environ 18 000 clients reçoivent la mise à jour piégée | provenance du build (SLSA) |
| ua-parser-js (2021) | dépendance | le compte npm du mainteneur est piraté, trois versions publiées avec un mineur et un voleur de mots de passe | lock, épinglage, Trusted Publishing |
| xz utils (2024) | code source | une porte dérobée introduite après deux ans d'ingénierie sociale envers le mainteneur (CVE-2024-3094) | revue à deux, provenance des sources |
| Polyfill.io (2024) | distribution | le domaine du CDN racheté sert du code malveillant à plus de 100 000 sites | intégrité des ressources, auto-hébergement |
| Shai-Hulud (2025) | dépendance | un ver npm vole des jetons de publication et se republie : plus de 500 paquets en septembre, environ 800 en novembre | Trusted Publishing, --ignore-scripts |
L'OWASP en a tiré les conséquences : dans son Top 10:2025, la catégorie A03 Software Supply Chain Failures arrive troisième, et la moitié des répondants de son enquête communautaire l'ont classée première préoccupation. En 2026, Trivy lui-même, un scanner de sécurité, a été compromis : la leçon sur Trivy en détaille l'incident.
Les trois questions : transparence, intégrité, provenance
Section intitulée « Les trois questions : transparence, intégrité, provenance »Toute la sécurité de la supply chain se ramène à trois questions. Si l'une reste sans réponse vérifiable, la chaîne a un trou, quel que soit le soin mis dans les deux autres.
| Question | Ce qu'elle demande | Réponse outillée |
|---|---|---|
| Transparence | Qu'est-ce qui compose mon logiciel ? | un SBOM |
| Intégrité | L'artefact a-t-il été modifié depuis sa fabrication ? | une signature |
| Provenance | De quel commit et de quel build vient-il ? | une attestation SLSA |
Les trois se tiennent. Un SBOM non signé peut être falsifié par celui qui modifie l'image. Une signature prouve qu'un artefact n'a pas changé, pas ce qu'il contient. Une attestation de provenance dit d'où vient l'image, pas si elle embarque une dépendance vulnérable. Les leçons suivantes du module traitent chacune une de ces réponses.
Le schéma ci-dessous place chaque réponse sur la chaîne : le SBOM inventorie les dépendances, l'attestation de provenance naît au build, et la signature accompagne l'artefact jusqu'à l'admission, où elle est vérifiée avant le déploiement.
SBOM : savoir ce qu'on livre
Section intitulée « SBOM : savoir ce qu'on livre »Un SBOM (Software Bill of Materials) est l'inventaire de tous les
composants d'un logiciel : dépendances directes et transitives, versions
exactes, licences et identifiants standard (purl). C'est lui qui permet de
répondre en quelques minutes à « sommes-nous touchés par cette CVE ? », là où
Log4Shell a coûté des semaines d'audit manuel.
Deux formats dominent. CycloneDX, porté par l'OWASP et normalisé par l'Ecma sous la référence ECMA-424, est orienté sécurité et porte les déclarations VEX d'exploitabilité. SPDX, porté par la Linux Foundation et normalisé ISO/IEC 5962, vient de la conformité des licences. Les outils courants produisent les deux.
Produire un SBOM avec Syft
Section intitulée « Produire un SBOM avec Syft »Syft (Anchore) inventorie un dossier ou une image. La commande à retenir
est syft scan : l'ancienne forme syft packages, encore citée partout,
affiche désormais Command "packages" is deprecated, use syft scan instead
avec Syft 1.52.0. Sur l'application Express, le SBOM CycloneDX recense 71
composants : les 69 paquets npm, plus l'application et son lock.
$ syft scan dir:. -o cyclonedx-json > sbom.cdx.json$ jq '.specVersion, (.components | length)' sbom.cdx.json"1.7"71$ jq '.components[] | select(.name == "express") | {name, version, purl, licenses}' sbom.cdx.json{ "name": "express", "version": "4.21.2", "purl": "pkg:npm/express@4.21.2", "licenses": [ { "license": { "id": "MIT" } } ]}Le champ purl (package URL) est la clé qui relie le SBOM aux bases de
vulnérabilités. Produire, publier et exploiter cet inventaire est le sujet
de la leçon suivante, sur le SBOM.
SLSA : à quel point peut-on croire le build ?
Section intitulée « SLSA : à quel point peut-on croire le build ? »SLSA (Supply-chain Levels for Software Artifacts, prononcé « salsa ») est un cadre de l'OpenSSF qui gradue la confiance qu'on peut accorder à un artefact. Sa version 1.2, la version en vigueur, compte deux volets : le volet Build, qui juge la fabrication, et le volet Source, réintroduit dans cette version après avoir été retiré de la 1.0, qui juge la gestion du code.
| Niveau Build | Exigence | Ce que ça prouve |
|---|---|---|
| L0 | aucune | rien |
| L1 | une provenance existe | le build est documenté |
| L2 | provenance signée par une plateforme de build hébergée | elle n'a pas été falsifiée après coup |
| L3 | build isolé, secret de signature hors de portée des étapes du build | même un build compromis ne peut pas mentir sur sa provenance |
Le volet Source va de L1 (code sous gestion de versions) à L4 (revue par deux personnes de confiance sur les branches protégées). Côté outillage, GitHub l'écrit dans sa documentation : ses attestations d'artefacts fournissent seules le niveau Build L2, et un workflow réutilisable, qui sépare le build du workflow appelant, permet d'atteindre L3. La leçon sur la provenance SLSA montre comment la vérifier avant de déployer.
Signer sans gérer de clé : Sigstore
Section intitulée « Signer sans gérer de clé : Sigstore »Signer un artefact a longtemps voulu dire gérer une clé privée : la stocker, la renouveler, la révoquer si elle fuit. Presque personne ne le faisait. Sigstore, projet de l'OpenSSF, supprime la clé durable : la signature repose sur l'identité OIDC du signataire, par exemple le workflow GitHub Actions qui publie.
Trois briques coopèrent. Fulcio délivre un certificat de dix minutes lié à cette identité. Cosign signe l'artefact avec. Rekor enregistre la signature dans un journal de transparence public et inaltérable : le certificat expire, mais la signature reste vérifiable, et toute signature frauduleuse y laisse une trace.
# Signer une image par son digest, dans un job CI qui a l'identité OIDCcosign sign ghcr.io/acme/facturation@sha256:<digest>
# Vérifier : qui a signé, et depuis quel émetteur d'identitécosign verify \ --certificate-identity-regexp '^https://github.com/acme/facturation/' \ --certificate-oidc-issuer https://token.actions.githubusercontent.com \ ghcr.io/acme/facturation@sha256:<digest>La vérification compte plus que la signature : une image signée que personne ne vérifie ne protège rien. Dans un cluster, ce contrôle revient à un contrôleur d'admission comme Kyverno, qui refuse un pod dont l'image n'est pas signée par l'identité attendue. La leçon sur Cosign pratique la signature et ses échecs de vérification.
Trusted Publishing : publier sans jeton
Section intitulée « Trusted Publishing : publier sans jeton »Shai-Hulud a exploité le dernier maillon faible : des jetons de publication npm à longue durée de vie, volés sur des postes ou dans des variables de CI. Le Trusted Publishing, disponible sur npm et PyPI, remplace ce jeton par une authentification OIDC du pipeline auprès du registre, qui délivre un jeton éphémère. Le paquet publié porte alors une provenance signée. npm a révoqué ses anciens jetons classiques en décembre 2025, ce qui pousse tous les mainteneurs vers ce mode.
Durcir l'installation des dépendances
Section intitulée « Durcir l'installation des dépendances »Les dépendances sont le maillon le plus attaqué, parce que leur code s'exécute avec vos droits, souvent dès l'installation. Quatre gestes réduisent ce risque, et trois se vérifient en quelques secondes. La leçon sur la sécurisation des dépendances les décline par écosystème.
Épingler et verrouiller
Section intitulée « Épingler et verrouiller »Une plage de versions comme ^4.17.0 accepte toute version future
compatible, y compris une version piégée publiée demain. On épingle donc une
version exacte, et surtout on versionne le lock file, qui fige l'arbre
complet, dépendances transitives comprises, avec l'empreinte de chaque
paquet.
// ❌ À éviter : accepte n'importe quelle version future{ "dependencies": { "lodash": "^4.17.0", "express": "*" } }
// Version exacte, et package-lock.json versionné{ "dependencies": { "lodash": "4.17.21", "express": "4.21.2" } }En CI, on installe avec npm ci, jamais npm install. Mesuré avec npm
11.19.0 : quand package.json et le lock divergent, npm ci refuse
d'installer au lieu de réécrire le lock en silence.
$ npm cinpm error code EUSAGEnpm error `npm ci` can only install packages when your package.json and package-lock.jsonor npm-shrinkwrap.json are in sync. Please update your lock file with `npm install` before continuing.Vérifier les empreintes
Section intitulée « Vérifier les empreintes »Le lock porte l'empreinte SHA-512 de chaque paquet (champ integrity).
Si le registre, un miroir ou un proxy sert un fichier différent, l'installation
échoue. Mesuré en remplaçant l'empreinte d'Express dans le lock : npm ci
sort en code 1 sur une erreur EINTEGRITY.
$ npm cinpm error code EINTEGRITYnpm error sha512-AAAA…== integrity checksum failed when using sha512:wanted sha512-AAAA…== but got sha512-28HqgMZAmih1Czt9…== (58016 bytes)Python fait de même avec pip install --require-hashes, sur un fichier
produit par pip-compile --generate-hashes. Une subtilité, mesurée avec pip
26.1.2 : chaque paquet liste plusieurs empreintes, une par fichier publié,
et pip en accepte n'importe laquelle. Fausser une seule empreinte ne bloque
donc rien ; fausser toutes celles de requests fait échouer l'installation
avec THESE PACKAGES DO NOT MATCH THE HASHES FROM THE REQUIREMENTS FILE.
Couper les scripts d'installation
Section intitulée « Couper les scripts d'installation »Un paquet npm peut déclarer des scripts preinstall ou postinstall
exécutés à l'installation. C'est par un preinstall que Shai-Hulud 2.0
lançait sa charge, avant même que le code soit importé. L'option
--ignore-scripts les désactive : npm ci --ignore-scripts installe
l'arbre sans exécuter une ligne de code tiers. Quelques paquets en ont
besoin pour compiler un module natif ; on les traite alors un par un.
Scanner les vulnérabilités connues
Section intitulée « Scanner les vulnérabilités connues »Les trois gestes précédents protègent contre une substitution, pas contre
une faille connue dans une version légitime. Un scanner de composition
(SCA) compare les dépendances aux bases de CVE : npm audit, Trivy ou
Grype. Le module sur le code et les dépendances les a mesurés, avec leurs
codes de sortie, dans la leçon sur la
SCA.
Une chaîne complète dans un workflow
Section intitulée « Une chaîne complète dans un workflow »Ce workflow réunit les trois réponses au moment de la publication d'une version : il construit l'image, atteste sa provenance avec l'action officielle de GitHub (niveau Build L2) et produit son SBOM, archivé avec le run. Chaque action est épinglée sur le SHA de son commit, et le workflow passe actionlint, zizmor 1.30.0 et poutine sans constat.
name: release
on: push: tags: - "v*"
permissions: {}
jobs: build: runs-on: ubuntu-24.04 permissions: contents: read packages: write id-token: write attestations: write env: IMAGE: ghcr.io/acme/facturation steps: - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: persist-credentials: false
- name: Construire et pousser l'image id: push env: TAG: ${{ github.ref_name }} GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: | echo "$GH_TOKEN" | docker login ghcr.io -u "$GITHUB_ACTOR" --password-stdin docker build -t "$IMAGE:$TAG" . docker push "$IMAGE:$TAG" digest=$(docker inspect --format='{{index .RepoDigests 0}}' "$IMAGE:$TAG" | cut -d@ -f2) echo "digest=$digest" >> "$GITHUB_OUTPUT"
- name: Attester la provenance uses: actions/attest-build-provenance@4d101475d8b20a2381f78447822ac1eab6504dd8 # v4.2.2 with: subject-name: ${{ env.IMAGE }} subject-digest: ${{ steps.push.outputs.digest }} push-to-registry: true
- name: Générer le SBOM uses: anchore/sbom-action@3ad7283483fc7af8ff2b4ea19663c2d5ca935e26 # v0.24.2 with: image: ${{ env.IMAGE }}@${{ steps.push.outputs.digest }} format: cyclonedx-json output-file: sbom.cdx.json registry-username: ${{ github.actor }} registry-password: ${{ secrets.GITHUB_TOKEN }}Le tag Git n'apparaît jamais directement dans le script : il passe par la
variable TAG, ce qui évite une injection de commande par un nom de
tag forgé. L'action sbom-action archive elle-même le SBOM comme artefact du
run, son option upload-artifact valant true par défaut.
Par où commencer ?
Section intitulée « Par où commencer ? »Tout mettre en place d'un coup échoue presque toujours. L'ordre qui fonctionne suit les trois questions, de la moins coûteuse à la plus exigeante, et chaque étape apporte une protection utile avant la suivante.
-
Inventorier : un SBOM à chaque build des projets critiques, et un scanner de dépendances en CI.
-
Verrouiller : lock files versionnés,
npm ci --ignore-scripts, empreintes vérifiées, Trusted Publishing pour vos propres paquets. -
Prouver : images signées avec Cosign et attestations de provenance, niveau Build L2.
-
Imposer : vérification des signatures à l'admission dans le cluster, puis niveau L3 avec un workflow de build réutilisable.
À retenir
Section intitulée « À retenir »- La supply chain va du code source à la distribution ; chaque maillon a déjà été attaqué.
- 98 % des applications contiennent de l'open source, 70 % de leur code en moyenne (OSSRA 2026).
- Trois questions : transparence (SBOM), intégrité (signature), provenance (attestation SLSA).
- Un SBOM se produit avec
syft scan, pas l'ancienne formesyft packages. - SLSA 1.2 a deux volets : Build (L0 à L3) et Source (L1 à L4) ; les attestations GitHub donnent seules Build L2.
- Sigstore signe sans clé durable : certificat Fulcio de dix minutes, trace publique dans Rekor.
- En CI :
npm ci --ignore-scripts, lock versionné, empreintes vérifiées ; pip n'échoue que si aucune empreinte listée ne correspond.
Contrôle de connaissances
Section intitulée « Contrôle de connaissances »Vérifiez que l'essentiel de cette leçon est acquis. Les questions portent uniquement sur ce qui vient d'être expliqué ici.
Contrôle de connaissances
Validez vos connaissances avec ce quiz interactif
Informations
- Le chronomètre démarre au clic sur Démarrer
- Questions à choix multiples, vrai/faux et réponses courtes
- Vous pouvez naviguer entre les questions
- Les résultats détaillés sont affichés à la fin
Lance le quiz et démarre le chronomètre
Vérification
(0/0)Score par domaine
Un domaine regroupe plusieurs guides et reçoit plusieurs questions : son score est plus fiable qu'un score par thème, qui porte souvent sur une seule question.
Bilan
Points forts
Aucun sujet réussi à 80 % sur au moins deux questions pour l’instant.
Points faibles
Aucun sujet sous le seuil de réussite.
À faire ensuite
Des indices pour retenter votre chance ?
Continuer le cours : La confiance transitive : hériter du risque de sa chaîne
Nouveau quiz complet avec des questions aléatoires
Retravailler uniquement les questions ratées
Retour à la liste des certifications
FAQ : questions fréquentes
Section intitulée « FAQ : questions fréquentes »Les questions ci-dessous reprennent les doutes les plus courants sur la supply chain logicielle : SBOM, SLSA, Sigstore et protection des dépendances, avec les mêmes versions mesurées que la leçon.
| Maillon | Exemple d'attaque |
|---|---|
| Code source | xz utils (2024) |
| Dépendances | ua-parser-js (2021), Shai-Hulud (2025) |
| Build | SolarWinds (2020) |
| Distribution | Polyfill.io (2024) |
| Question | Réponse | Outil courant |
|---|---|---|
| Transparence : qu'est-ce qui compose mon logiciel ? | SBOM | Syft, Trivy |
| Intégrité : a-t-il été modifié ? | signature | Cosign (Sigstore) |
| Provenance : de quel build vient-il ? | attestation SLSA | actions/attest-build-provenance |
Avec Syft
syft scan dir:. -o cyclonedx-json > sbom.cdx.json
jq '.specVersion, (.components | length)' sbom.cdx.json
Mesuré avec Syft 1.52.0 sur une application qui ne déclare qu'Express : CycloneDX 1.7, 71 composants. La forme syft packages affiche Command "packages" is deprecated, use syft scan instead.Avec Trivy
trivy fs --format cyclonedx -o sbom.cdx.json .
En CI, anchore/sbom-action produit le SBOM d'une image et l'archive comme artefact du run.Volet Build
| Niveau | Exigence |
|---|---|
| L1 | une provenance existe |
| L2 | provenance signée par une plateforme de build hébergée |
| L3 | build isolé, secret de signature hors de portée du build |
Volet Source
De L1 (code sous gestion de versions) à L4 (revue par deux personnes de confiance sur les branches protégées). Retiré de la version 1.0, il est revenu dans SLSA 1.2.En pratique
GitHub l'écrit : ses attestations d'artefacts fournissent seules Build L2 ; un workflow réutilisable qui isole le build permet d'atteindre L3.- Fulcio délivre un certificat valable dix minutes ;
- Cosign signe l'artefact ;
- Rekor garde la signature dans un journal de transparence public.
cosign verify \
--certificate-identity-regexp '^https://github.com/acme/facturation/' \
--certificate-oidc-issuer https://token.actions.githubusercontent.com \
ghcr.io/acme/facturation@sha256:<digest>
La signature ne protège que si elle est vérifiée, en CI ou à l'admission dans le cluster.- le pipeline prouve son identité par OIDC ;
- le registre délivre un jeton éphémère ;
- le paquet publié porte une provenance signée.
Les gestes, mesurés avec npm 11.19.0
| Geste | Ce qu'il bloque |
|---|---|
| Version exacte + lock versionné | une version piégée publiée demain |
npm ci |
refuse un lock désynchronisé (EUSAGE) |
Empreinte integrity |
refuse un fichier substitué (EINTEGRITY) |
--ignore-scripts |
la charge lancée par un script preinstall |
| Scanner SCA | une CVE connue dans une version légitime |
npm ci --ignore-scripts
Côté Python, pip install --require-hashes sur un fichier produit par pip-compile --generate-hashes. Attention : pip accepte un fichier s'il correspond à n'importe laquelle des empreintes listées pour le paquet.