Aller au contenu
Culture DevOps high

Sécurité supply chain logicielle : SBOM, SLSA, Sigstore

30 min de lecture

En décembre 2021, la vulnérabilité 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.

Cette crise a révélé un problème structurel : nous ne savons pas ce qui compose nos logiciels. La supply chain logicielle, l'ensemble des composants, processus et personnes impliqués dans la création d'un logiciel, est devenue le maillon faible de la sécurité. Cette page s'adresse aux développeurs, ingénieurs DevOps et responsables sécurité qui doivent comprendre ces risques et mettre en place des garde-fous concrets : SBOM pour l'inventaire, SLSA pour la maturité du build, Sigstore pour la signature, et des pratiques de gestion des dépendances directement applicables en CI/CD.

  • Comprendre les risques de la supply chain logicielle à travers des attaques réelles (SolarWinds, xz utils, Shai-Hulud)
  • Générer et exploiter un SBOM (CycloneDX, SPDX) pour répondre en quelques minutes à une CVE critique
  • Situer votre chaîne de build sur les niveaux SLSA (0 à 3) et automatiser la génération de provenance
  • Signer vos artefacts sans gérer de clé privée grâce à Sigstore (Cosign, Fulcio, Rekor)
  • Sécuriser vos dépendances : épingler, verrouiller, scanner, vérifier les checksums
  • Construire une roadmap progressive de maturité supply chain, de la visibilité à la provenance

Analogie : Imaginez la construction d'une voiture. Vous ne fabriquez pas chaque vis, chaque boulon, chaque composant électronique. Vous les achetez à des fournisseurs. Si l'un d'eux vous livre des freins défectueux, votre voiture sera dangereuse, même si votre assemblage est parfait.

En développement logiciel, c'est identique. 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 en production. Chaque maillon peut être compromis, et une seule faille suffit à contaminer l'ensemble.

Voici les composants typiques d'une supply chain logicielle, avec les risques spécifiques à chaque étape :

ComposantExemplesRisques associés
Code sourceVotre code, contributions externesInjection de code malveillant
Dépendancesnpm, PyPI, Maven, Go modulesCVE, typosquatting, compte compromis
Outils de buildCompilateurs, bundlers, CI/CDCompromission du processus de build
ArtefactsImages Docker, binaires, packagesTampering, substitution
InfrastructureRegistries, CDN, serveurs de déploiementMan-in-the-middle, compromission

Chaque ligne de ce tableau représente un point d'entrée potentiel pour un attaquant. Une dépendance compromise peut exfiltrer vos secrets. Un outil de build modifié peut injecter un backdoor. Une infrastructure piratée peut distribuer une version corrompue de votre application.

Les chiffres donnent le vertige :

  • Plus de 80% du code d'une application moderne provient de dépendances tierces, un ratio stable depuis plusieurs années dans les rapports sectoriels (Sonatype, Synopsys OSSRA)
  • En 2025, Sonatype a recensé plus de 454 000 nouveaux paquets malveillants publiés sur les registries publics (npm, PyPI, Maven Central, NuGet, Hugging Face), portant le total cumulé détecté à plus de 1,2 million de paquets, avec plus de 99% concentrés sur npm
  • Une application Node.js moderne peut compter plusieurs centaines, voire plus d'un millier, de dépendances une fois l'arbre transitif complet déplié
  • Le délai de détection d'un paquet compromis varie énormément : de quelques jours pour les cas les plus visibles à plus d'un an pour les attaques les plus discrètes

Ce que ces chiffres signifient concrètement : Quand vous écrivez une application de 10 000 lignes de code, vous faites en réalité confiance à 40 000 lignes de code écrites par des inconnus. Si l'un de ces auteurs voit son compte npm compromis, votre application peut devenir un vecteur d'attaque, souvent sans que personne ne s'en rende compte pendant des mois.

Cette gravité n'a pas échappé à l'OWASP (Open Web Application Security Project) : dans son Top 10:2025, publié début 2026, la catégorie A03, Software Supply Chain Failures entre directement à la troisième place du classement, avec le taux d'incidence moyen le plus élevé de toutes les catégories. Ce basculement confirme que la supply chain n'est plus un sujet périphérique du Top 10 OWASP appliqué au DevSecOps, mais un pilier central de toute stratégie de sécurité applicative.

Face à la complexité de la supply chain, trois questions fondamentales émergent. Si vous ne pouvez pas y répondre avec certitude, vous êtes vulnérable.

Premier réflexe : Face à une nouvelle CVE critique (comme Log4Shell), pouvez-vous identifier en moins de 10 minutes tous les systèmes affectés ? Si la réponse est "non", c'est un problème de transparence.

Deuxième réflexe : Quand vous déployez une image Docker en production, êtes-vous sûr qu'elle n'a pas été modifiée entre le build et le déploiement ? Si vous ne pouvez pas le prouver, c'est un problème d'intégrité.

Troisième réflexe : Pouvez-vous affirmer que votre artefact provient exactement du commit Git que vous pensez, construit par votre CI/CD officiel ? Si vous devez fouiller dans les logs pour vérifier, c'est un problème de provenance.

Voici comment ces trois piliers se matérialisent techniquement :

PilierQuestionSolution
TransparenceQu'est-ce qui compose mon logiciel ?SBOM
IntégritéMon logiciel a-t-il été modifié ?Signatures, SLSA
ProvenanceD'où vient mon logiciel ?Attestations, logs de transparence

Pourquoi ces trois piliers sont indissociables : Un SBOM (transparence) sans signature (intégrité) peut être falsifié par un attaquant. Une signature sans SBOM ne vous 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 l'intersection des trois qui crée la sécurité.

Analogie : Quand vous achetez un produit alimentaire, vous lisez la liste des ingrédients. Farine, eau, sel, conservateurs. Si demain un conservateur est déclaré cancérigène, le fabricant peut rappeler tous les produits qui en contiennent. Sans cette liste, impossible de savoir quels produits sont concernés.

Un SBOM (Software Bill of Materials) est exactement cette liste d'ingrédients, mais pour le logiciel. C'est l'inventaire exhaustif de tous les composants qui composent votre application :

  • Dépendances directes : les bibliothèques que vous avez explicitement ajoutées (npm install express)
  • Dépendances transitives : les bibliothèques utilisées par vos dépendances (express dépend de 50+ packages)
  • Versions exactes : pas "lodash 4.x", mais "lodash 4.17.21"
  • Licences : MIT, Apache 2.0, GPL, crucial pour la conformité juridique
  • Hashes : empreintes cryptographiques pour vérifier l'intégrité

Sans SBOM, vous êtes aveugle. Quand une vulnérabilité comme Log4Shell est annoncée, vous devez pouvoir répondre en minutes, pas en semaines :

QuestionSans SBOMAvec SBOM
Suis-je affecté par CVE-2024-XXXX ?"Je ne sais pas, il faut vérifier"Requête automatique : oui/non
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

Un SBOM, c'est comme un format de facture : tout le monde pourrait inventer le sien, mais pour que les systèmes se parlent, il faut des standards. Deux formats se sont imposés, chacun avec son histoire et ses forces.

CycloneDX vient du monde de la sécurité applicative (OWASP, les gens qui maintiennent le Top 10 des vulnérabilités web). Il est optimisé pour répondre rapidement à une CVE : métadonnées de sécurité riches, support natif des VEX (Vulnerability Exploitability eXchange, pour dire "oui la CVE existe, mais elle n'est pas exploitable dans mon contexte"). La spécification a atteint la version 1.7 fin 2025, désormais reconnue comme standard ECMA-424.

SPDX vient du monde de l'open source Linux Foundation. Il est standardisé ISO et se concentre sur la conformité juridique : qui a écrit quoi, sous quelle licence, avec quelles obligations. La version 3.0, sortie en 2024, introduit une architecture par profils (sécurité, licences, build, IA) qui étend le socle commun selon le cas d'usage. Si votre entreprise doit prouver qu'elle respecte les licences GPL, SPDX est votre allié.

FormatOrigineForcesCas d'usage
CycloneDXOWASPRiche en métadonnées de sécurité, VEX intégréSécurité, vulnérabilités
SPDXLinux FoundationStandard ISO, focus licencesConformité, juridique

En pratique : Si votre priorité est la sécurité (réagir vite aux CVE), choisissez CycloneDX. Si votre priorité est la conformité légale, choisissez SPDX. Les deux formats coexistent, et les outils modernes supportent généralement les deux.

{
"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" }}]
}
]
}

Plusieurs outils open source génèrent un SBOM directement depuis votre code ou votre image Docker, sans configuration lourde. Syft (Anchore) est le plus polyvalent : il détecte les paquets de dizaines d'écosystèmes (npm, pip, Go, Maven, RPM, APK) et exporte aussi bien en CycloneDX qu'en SPDX. Trivy a l'avantage de combiner génération de SBOM et scan de vulnérabilités dans un seul outil, ce qui simplifie l'intégration en CI/CD. Le choix dépend surtout de l'existant : si un scanner tourne déjà dans votre pipeline, réutiliser sa fonction SBOM évite d'ajouter un outil de plus.

Fenêtre de terminal
# Avec Syft (Anchore) - recommandé
syft packages dir:. -o cyclonedx-json > sbom.json
# Avec Trivy
trivy fs --format cyclonedx -o sbom.json .
# Pour une image Docker
syft packages registry.example.com/myapp:v1.0.0 -o spdx-json > sbom.json

Pour un tour d'horizon plus complet des formats, des outils et des cas d'usage juridiques du SBOM, consultez le guide dédié SBOM : comprendre le Software Bill of Materials.

Générer un SBOM une fois sur votre poste ne sert à rien si personne ne le refait au commit suivant. L'inventaire doit être produit automatiquement à chaque build, sinon il devient obsolète dès que la première dépendance change. L'exemple ci-dessous génère et archive un SBOM CycloneDX à chaque push sur main, avec les permissions minimales et un checkout qui ne persiste pas d'identifiants.

name: Generate SBOM
on:
push:
branches: [main]
permissions: {}
jobs:
sbom:
runs-on: ubuntu-latest
permissions:
contents: read
steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
persist-credentials: false
- name: Generate SBOM
uses: anchore/sbom-action@e22c389904149dbc22b58101806040fa8d37a610 # v0.24.0
with:
format: cyclonedx-json
output-file: sbom.json
- name: Upload SBOM
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: sbom
path: sbom.json

SLSA (Supply-chain Levels for Software Artifacts, prononcé "salsa") est un framework qui définit des niveaux de sécurité progressifs pour la chaîne de build.

Analogie : Pensez aux normes de sécurité automobile. Une voiture peut avoir :

  • Niveau 0 : Aucune garantie (pas même une ceinture de sécurité documentée)
  • Niveau 1 : Des ceintures de sécurité (c'est mieux que rien, mais ça reste déclaratif)
  • Niveau 2 : Des airbags homologués en usine (protection automatique, garantie par le fabricant)
  • Niveau 3 : ABS + contrôle de stabilité isolé du conducteur (même le constructeur ne peut pas le désactiver discrètement)

SLSA fait la même chose pour le logiciel. Depuis la version 1.0 du framework, publiée en 2023 et affinée jusqu'à la 1.2 actuelle, le volet "Source" historique a été retiré pour se concentrer sur le track Build : quatre niveaux mesurables (0 à 3, il n'existe plus de niveau 4) qui répondent à une question : Peut-on faire confiance à cet artefact ?

Chaque niveau rajoute des garanties techniques qui rendent la falsification plus difficile :

NiveauExigencesCe que ça prouveEffort
SLSA 0Aucune exigenceAbsence de toute garantie formelle-
SLSA 1Provenance générée et distribuableLe build est documenté et traçableFaible
SLSA 2Provenance signée, build sur plateforme hébergéeLe processus n'a pas été altéré après coupMoyen
SLSA 3Build isolé, secrets de signature inaccessibles aux étapes définies par l'utilisateurMême un accès root au runner ne permet pas de falsifier la provenanceÉlevé

Pourquoi une progression ? Parce que viser directement le niveau 3 est irréaliste pour la plupart des organisations. SLSA 2 est un bon compromis : la provenance est générée automatiquement par votre CI/CD (GitHub Actions, GitLab CI), donc un développeur malveillant ne peut pas la modifier facilement. SLSA 3 va plus loin : même avec un accès root au runner CI, la falsification devient extrêmement difficile parce que le secret de signature n'est jamais exposé aux étapes de build définies par l'utilisateur.

Une attestation de provenance SLSA contient :

{
"_type": "https://in-toto.io/Statement/v1",
"subject": [{
"name": "ghcr.io/myorg/myapp",
"digest": { "sha256": "abc123..." }
}],
"predicateType": "https://slsa.dev/provenance/v1",
"predicate": {
"buildDefinition": {
"buildType": "https://github.com/slsa-framework/slsa-github-generator/container@v2",
"externalParameters": {
"source": {
"uri": "git+https://github.com/myorg/myapp@refs/heads/main",
"digest": { "sha1": "def456..." }
}
}
},
"runDetails": {
"builder": { "id": "https://github.com/slsa-framework/slsa-github-generator/.github/workflows/generator_container_slsa3.yml@refs/tags/v2.1.0" },
"metadata": {
"invocationId": "https://github.com/myorg/myapp/actions/runs/123456789"
}
}
}
}

Cette attestation prouve :

  • Quoi : L'image ghcr.io/myorg/myapp avec ce digest
  • D'où : Du repo myorg/myapp, commit def456...
  • Comment : Via le workflow GitHub Actions generator_container_slsa3.yml
  • Quand : Run ID 123456789

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

name: Release with SLSA
on:
push:
tags: ['v*']
permissions: {}
jobs:
build:
outputs:
digest: ${{ steps.build.outputs.digest }}
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
persist-credentials: false
- name: Build and push
id: build
run: |
docker build -t ghcr.io/${{ github.repository }}:${{ github.ref_name }} .
docker push ghcr.io/${{ github.repository }}:${{ github.ref_name }}
echo "digest=$(docker inspect --format='{{index .RepoDigests 0}}' ghcr.io/${{ github.repository }}:${{ github.ref_name }} | cut -d'@' -f2)" >> $GITHUB_OUTPUT
provenance:
needs: build
permissions:
actions: read
id-token: write
packages: write
uses: slsa-framework/slsa-github-generator/.github/workflows/generator_container_slsa3.yml@f7dd8c54c2067bafc12ca7a55595d5ee9b75204a # v2.1.0
with:
image: ghcr.io/${{ github.repository }}
digest: ${{ needs.build.outputs.digest }}
registry-username: ${{ github.actor }}
secrets:
registry-password: ${{ secrets.GITHUB_TOKEN }}

Sigstore simplifie radicalement la signature d'artefacts en éliminant le problème le plus complexe : la gestion des clés privées.

Le problème historique : pourquoi personne ne signait

Section intitulée « Le problème historique : pourquoi personne ne signait »

Imaginez que pour prouver votre identité, vous deviez porter en permanence un coffre-fort contenant votre passeport. Si vous le perdez, votre identité est volée. Si quelqu'un le vole, il peut se faire passer pour vous. Vous devez le garder accessible 24/7 (pour prouver qui vous êtes), mais absolument sécurisé (pour qu'on ne vous le vole pas). C'est impossible.

Avant Sigstore, signer un artefact logiciel était exactement ce cauchemar :

  1. Générer une paire de clés : Créer une clé privée (votre passeport numérique)
  2. Stocker la clé privée de manière sécurisée : Coffre-fort chiffré, HSM, KMS, coûteux
  3. Distribuer la clé publique : Comment les autres savent-ils que cette clé publique est vraiment la vôtre ?
  4. Gérer la rotation des clés : Changer de clé tous les X mois (cauchemar opérationnel)
  5. Révoquer les clés compromises : Si la clé fuite, comment annuler toutes les signatures passées ?

Résultat : la grande majorité des projets open source ne signaient rien. C'était trop complexe, trop cher, trop risqué. Les développeurs préféraient ne rien faire plutôt que de mal gérer une clé privée.

Sigstore résout ce problème avec une idée brillante : et si on n'avait pas besoin de gérer des clés privées ?

Sigstore utilise des certificats éphémères liés à votre identité OIDC (GitHub, GitLab, Google). Voici comment ça fonctionne concrètement :

Scénario : Vous êtes développeur chez Acme Corp. Votre CI/CD GitHub Actions doit signer une image Docker.

  1. Vous vous authentifiez via OIDC : Votre workflow GitHub Actions prouve son identité auprès de Sigstore : "Je suis le workflow release.yml du repo acme/app, déclenché par le tag v1.0.0, par l'utilisateur alice."

  2. Fulcio émet un certificat de courte durée (10 minutes) : Sigstore vous donne un certificat qui dit : "Ce certificat est valide pendant 10 minutes et atteste que le signataire est bien le workflow GitHub Actions de acme/app."

  3. Vous signez avec ce certificat : Votre image Docker ghcr.io/acme/app:v1.0.0 est signée avec ce certificat temporaire.

  4. La signature est enregistrée dans Rekor (log de transparence) : Un registre public et immuable enregistre que le workflow acme/app/.github/workflows/release.yml a signé l'image sha256:abc123 à une date donnée.

  5. Le certificat expire, mais la signature reste vérifiable : 10 minutes plus tard, le certificat est inutilisable. Mais n'importe qui peut vérifier la signature en consultant Rekor : "Cette image a bien été signée par le workflow officiel d'Acme Corp."

Résultat : Pas de clé privée à gérer (pas de risque de fuite), mais une traçabilité complète et vérifiable publiquement. Si un attaquant compromet votre repo, il peut signer une fois pendant 10 minutes, mais chaque signature est enregistrée dans Rekor. L'attaque sera visible.

Sigstore n'est pas un outil unique mais un écosystème de trois briques qui coopèrent : une pour signer, une pour certifier l'identité du signataire, une pour enregistrer publiquement l'événement.

ComposantRôleAnalogie
CosignCLI pour signer/vérifierLe stylo qui signe
FulcioAutorité de certificationLe notaire qui vérifie l'identité
RekorLog de transparenceLe registre public des actes
GitsignSignature des commits GitCosign pour Git

Depuis octobre 2025, Rekor v2 est passé en disponibilité générale : le log de transparence repose désormais sur une architecture en tuiles (Trillian-Tessera) qui réduit fortement le coût d'exploitation côté Sigstore, sans rien changer à votre usage quotidien de Cosign. Les versions récentes du client (Cosign 2.6.0+ ou 3.0.1+) basculent automatiquement vers ce nouveau backend.

Cosign est l'outil en ligne de commande de Sigstore : il signe et vérifie des images conteneurs (ou tout autre artefact OCI) en une seule commande. Deux approches coexistent. La signature keyless, recommandée, s'appuie sur votre identité OIDC (GitHub Actions, GitLab CI) sans jamais manipuler de clé privée. La signature avec clé, plus classique, reste utile quand votre organisation impose déjà une gestion de clés (HSM, KMS) ou fonctionne dans un environnement air-gapped sans accès à Fulcio.

Fenêtre de terminal
# Signer (ouvre une fenêtre d'authentification OIDC)
cosign sign ghcr.io/myorg/myapp:v1.0.0
# Vérifier
cosign verify \
--certificate-identity "https://github.com/myorg/myrepo/.github/workflows/release.yml@refs/tags/v1.0.0" \
--certificate-oidc-issuer "https://token.actions.githubusercontent.com" \
ghcr.io/myorg/myapp:v1.0.0

Sigstore ne protège que ce qui est effectivement signé. Or l'attaque Shai-Hulud (2025) a justement exploité le maillon le plus faible restant : des jetons npm à longue durée de vie, volés sur des postes de développeurs ou dans des variables d'environnement CI, permettant de republier automatiquement de nouveaux paquets infectés.

Depuis 2025, npm et PyPI répondent avec le Trusted Publishing : au lieu d'un jeton stocké en secret CI, le pipeline s'authentifie via OIDC directement auprès du registry, qui délivre un jeton de publication éphémère valable quelques minutes. Un paquet publié via Trusted Publishing est signé automatiquement par Sigstore, avec sa provenance publiée sans configuration supplémentaire. npm a définitivement désactivé ses anciens jetons classiques en décembre 2025, ce qui rend cette méthode incontournable pour tout mainteneur de paquet public.

Générer et vérifier des signatures ne sert à rien si le cluster accepte quand même une image non signée. Kubernetes délègue ce contrôle à un admission controller, un composant qui intercepte chaque création de Pod et peut la refuser avant qu'elle n'atteigne un nœud. Kyverno est l'un des plus utilisés pour cet usage : sa ressource ImageValidatingPolicy bloque le déploiement de toute image qui ne porte pas une signature Cosign valide, sans action manuelle du développeur à chaque mise en production.

# ImageValidatingPolicy Kyverno
apiVersion: policies.kyverno.io/v1
kind: ImageValidatingPolicy
metadata:
name: verify-signatures
spec:
validationActions: [Deny]
matchConstraints:
resourceRules:
- apiGroups: [""]
apiVersions: ["v1"]
operations: ["CREATE", "UPDATE"]
resources: ["pods"]
matchImageReferences:
- glob: "ghcr.io/myorg/*"
attestors:
- name: cosign-key
cosign:
key:
data: |-
-----BEGIN PUBLIC KEY-----
...
-----END PUBLIC KEY-----
validations:
- expression: "true"
message: "Image must be signed with our Cosign key."

Cette politique refuse (validationActions: [Deny]) toute création ou mise à jour de Pod dont l'image ghcr.io/myorg/* ne correspond pas à la clé publique déclarée dans l'attestor cosign-key. En production, la vérification keyless (identité OIDC du workflow CI/CD plutôt qu'une clé statique à stocker et faire tourner) est généralement préférable à l'approche par clé montrée ici.

Les dépendances sont le vecteur d'attaque le plus courant dans la supply chain logicielle. La raison est simple : vous ne contrôlez pas leur code, mais vous l'exécutez avec les mêmes privilèges que le vôtre.

Scénario réel : En 2021, un développeur a compromis son propre package npm ua-parser-js (des millions de téléchargements par semaine) pour y injecter un cryptominer. En quelques heures, des milliers d'applications ont commencé à miner de la cryptomonnaie pour l'attaquant, sans que personne ne s'en rende compte. Pourquoi ? Parce que les versions n'étaient pas épinglées, et que npm install a automatiquement téléchargé la version compromise.

Plusieurs pratiques complémentaires permettent de réduire ce risque de manière pragmatique. Le guide Sécuriser les dépendances npm, PyPI et Go détaille ces pratiques écosystème par écosystème, avec les commandes spécifiques à chaque gestionnaire de paquets.

Épingler les versions : arrêter de faire confiance aux futurs

Section intitulée « Épingler les versions : arrêter de faire confiance aux futurs »

Quand vous écrivez "lodash": "^4.17.0" dans votre package.json, vous dites à npm : "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 demain le compte npm du mainteneur de lodash est compromis (mot de passe faible, pas de 2FA), l'attaquant peut publier lodash@4.17.22 avec un backdoor. Votre prochain npm install téléchargera cette version malveillante. Vous aurez fait confiance à une version que vous n'avez jamais testée.

Ne laissez jamais le gestionnaire de packages choisir la version pour vous :

// Dangereux
{
"dependencies": {
"lodash": "^4.17.0",
"express": "*"
}
}
// Sécurisé
{
"dependencies": {
"lodash": "4.17.21",
"express": "4.18.2"
}
}

Épingler les versions dans package.json ne suffit pas. Pourquoi ? Parce que vos dépendances ont elles-mêmes des dépendances (dépendances transitives), et vous ne contrôlez pas leurs versions.

Exemple : Vous épinglez express@4.18.2. Mais Express dépend de body-parser, qui dépend de iconv-lite, qui dépend de safer-buffer. Si demain safer-buffer publie une nouvelle version avec un malware, et que iconv-lite accepte cette version, votre build téléchargera le malware même si vous n'avez jamais entendu parler de safer-buffer.

Les lock files (package-lock.json, yarn.lock, Pipfile.lock) résolvent ce problème en figeant l'arbre complet des dépendances : chaque package, chaque version, chaque hash. C'est une photo complète de l'état du monde au moment du lock.

Fenêtre de terminal
# Installer uniquement ce qui est dans le lock file
npm ci # Pas `npm install`

Pourquoi npm ci et pas npm install ? Parce que npm install peut mettre à jour le lock file si de nouvelles versions compatibles sont disponibles. npm ci refuse : il installe exactement ce qui est dans le lock file, ou il échoue. C'est ce que vous voulez en CI/CD.

Vérifier les checksums : détecter les substitutions

Section intitulée « Vérifier les checksums : détecter les substitutions »

Le problème : Même avec un lock file, un attaquant qui contrôle le registry (ou un man-in-the-middle) peut substituer un package par une version malveillante qui porte le même nom et la même version.

La solution : Les lock files modernes incluent des hashes cryptographiques (SHA-512) de chaque package. Si le contenu téléchargé ne correspond pas au hash attendu, l'installation échoue.

Fenêtre de terminal
# npm vérifie automatiquement les checksums du lock file
npm ci --ignore-scripts # Bonus : désactive les scripts post-install
# Python avec pip-tools
pip-compile requirements.in --generate-hashes
pip-sync requirements.txt

Pourquoi --ignore-scripts ? Parce que certains packages npm exécutent des scripts arbitraires après installation (post-install hooks). Si un package est compromis, ce script peut exfiltrer vos secrets. En désactivant les scripts, vous limitez la surface d'attaque.

Scanner les vulnérabilités : réagir aux CVE connues

Section intitulée « Scanner les vulnérabilités : réagir aux CVE connues »

Le contexte : Chaque semaine, de nouvelles vulnérabilités (CVE) sont publiées. Si vous ne scannez pas vos dépendances, vous ne saurez pas que vous êtes vulnérable. C'est comme conduire une voiture rappelée pour défaut de frein sans le savoir.

Les scanners de vulnérabilités comparent vos dépendances à des bases de données de CVE connues (NVD, GitHub Advisory Database, etc.) et vous alertent instantanément.

Fenêtre de terminal
# npm audit (intégré à npm)
npm audit --audit-level=high
# Trivy (multi-écosystème : npm, pip, Go, Rust, Java...)
trivy fs --severity HIGH,CRITICAL .
# Grype (Anchore, alternative à Trivy)
grype dir:.

En pratique : Intégrez un de ces scanners dans votre CI/CD. Si une vulnérabilité HIGH ou CRITICAL est détectée, le build échoue, et vous forcez ainsi les équipes à corriger avant de déployer. Pour aller plus loin sur le triage et la remédiation une fois la CVE identifiée, consultez le guide Gestion des vulnérabilités CVE.

La sécurisation de la supply chain est un voyage, pas une destination. Plutôt que de tout implémenter d'un coup, adoptez une approche progressive qui construit la maturité par étapes :

  1. Mois 1-2 : Visibilité

    • Générer des SBOM pour les projets critiques
    • Scanner les dépendances (SCA) dans la CI
    • Inventorier les registries et sources de dépendances
  2. Mois 3-4 : Intégrité

    • Signer les images Docker avec Cosign
    • Vérifier les checksums des dépendances
    • Activer les lock files et npm ci
    • Migrer vers le Trusted Publishing (OIDC) pour vos propres paquets publiés
  3. Mois 5-6 : Provenance

    • Générer des attestations SLSA (niveau 2)
    • Configurer la vérification de signatures dans Kubernetes
    • Auditer les workflows CI/CD
  4. Mois 7+ : Maturité

    • Viser SLSA niveau 3
    • Déployer Dependency-Track pour le suivi centralisé
    • Automatiser la génération de VEX
  • SBOM : Savoir ce qui compose vos logiciels, obligatoire pour répondre aux CVE en minutes plutôt qu'en semaines
  • SLSA : Framework de maturité en 4 niveaux (0 à 3 depuis la v1.0), viser le niveau 2 minimum
  • Sigstore : Signature keyless via Cosign, Fulcio et Rekor, plus d'excuse pour ne pas signer
  • Trusted Publishing : OIDC remplace les jetons npm/PyPI longue durée, exploités par des attaques comme Shai-Hulud
  • Dépendances : Épingler, verrouiller, scanner, vérifier les checksums
  • OWASP : la supply chain est désormais classée 3e risque applicatif dans le Top 10:2025
  • Progressivité : Commencer par la visibilité, puis intégrité, puis provenance

Ce site vous est utile ?

Sachez que moins de 1% des lecteurs soutiennent ce site.

Je maintiens +700 guides gratuits, sans pub ni tracking. Un soutien, même symbolique, m'aide à couvrir l'hébergement et à garder ces ressources gratuites. Merci pour votre appui.

Le formulaire ne s'affiche pas ? Ouvrir Ko-fi dans un onglet.

Abonnez-vous et suivez mon actualité DevSecOps sur LinkedIn