SLSA : niveaux Build, provenance in-toto et vérification
- Accueil
- Développement, applications & chaîne logicielle
- SLSA : niveaux Build, provenance in-toto et vérification
SLSA : niveaux Build, provenance in-toto et vérification
Section intitulée « SLSA : niveaux Build, provenance in-toto et vérification »SLSA (Supply-chain Levels for Software Artifacts, prononcé « salsa ») est un cadre qui gradue la confiance qu’on peut accorder à la fabrication d’un artefact logiciel. Il ne juge pas le code. Il atteste qu’un binaire, un paquet ou une image sort bien d’un commit précis, construit par une plateforme identifiée, et que personne n’a pu réécrire ce récit en chemin.
Au rayon boucherie, l’étiquette de traçabilité indique d’où vient la viande et par quelles mains elle est passée avant d’arriver dans le frigo. Elle ne dit rien de la recette, ni du goût du plat. Elle évite seulement qu’on serve sous un faux nom un morceau d’origine inconnue. Pour un logiciel, ce même suivi existe, avec des niveaux d’exigence.
→ Lire l’explication complète de la marmotte
Attaques sur la chaîne de build : SolarWinds, xz-utils
Section intitulée « Attaques sur la chaîne de build : SolarWinds, xz-utils »La revue de code, les analyses statiques et la signature des commits protègent le dépôt source. Elles ne disent rien de ce qui se passe entre le dépôt et le fichier téléchargé. C’est précisément cet intervalle que visent les attaques les plus rentables, parce qu’un artefact compromis à la construction hérite de toute la légitimité du projet : même nom, même numéro de version, même certificat de signature.
SolarWinds (2020). Les attaquants n’ont pas modifié le dépôt source d’Orion. Un implant présent sur le serveur de build (baptisé SUNSPOT (nom donné à l’implant par CrowdStrike) dans les analyses publiées) substituait un fichier source pendant la compilation. La porte dérobée SUNBURST (nom donné par FireEye, qui l’a découverte) s’est donc retrouvée dans des binaires signés avec le certificat légitime de l’éditeur, puis distribués par le canal officiel de mise à jour. La signature du binaire était authentique. Elle certifiait fidèlement un résultat corrompu.
xz-utils (2024, CVE-2024-3094). Dans les versions 5.6.0 et 5.6.1, la porte dérobée visant liblzma, et par ricochet sshd sur certaines distributions, s’activait par un script m4 modifié qui figurait dans les archives de publication, mais pas dans le dépôt Git. La charge utile, elle, était cachée dans des fichiers de test binaires qui étaient bien versionnés. Le coupable était un mainteneur du projet. L’affaire montre deux choses distinctes. D’abord, une archive de release fabriquée à la main sur un poste et absente du dépôt constitue un angle mort. Ensuite, aucune attestation de fabrication n’arrête un mainteneur malveillant qui commite lui-même : la traçabilité aurait rendu l’écart entre l’archive et le dépôt visible, sans empêcher le reste.
Vingt ans de métier apprennent une constante : le maillon que personne ne regarde est toujours celui qui « tourne tout seul depuis des années », et c’est souvent la machine de build.
Ce que définit SLSA 1.0 : piste Build et niveaux
Section intitulée « Ce que définit SLSA 1.0 : piste Build et niveaux »SLSA est un projet de l’OpenSSF (Open Source Security Foundation), une fondation hébergée par la Linux Foundation. La version 1.0, publiée en 2023, a restructuré la spécification initiale (v0.1) autour de pistes indépendantes. La seule piste stabilisée en 1.0 est la piste Build. Les exigences sur le dépôt source, qui figuraient dans la v0.1, ont été retirées de cette version pour être retravaillées dans une piste Source séparée. Son état d’avancement est à vérifier sur slsa.dev au moment de s’y engager, car la spécification évolue par versions mineures.
Les niveaux de la piste Build, résumés sans prétendre remplacer le texte normatif :
| Niveau | Ce qu’il apporte | Ce qu’il laisse ouvert |
|---|---|---|
| Build L0 | Rien. C’est l’état par défaut. | Tout. |
| Build L1 | Une provenance existe et décrit comment l’artefact a été construit. | Elle peut être produite ou falsifiée par n’importe qui, y compris le projet. |
| Build L2 | Le build tourne sur une plateforme hébergée, qui génère et signe elle-même la provenance. | Une étape de build malveillante peut encore influencer d’autres builds ou accéder à la clé de signature. |
| Build L3 | La plateforme est durcie : isolation entre exécutions, et matériel de signature inaccessible aux étapes définies par l’utilisateur. | Ce qui se passe avant (source) et après (vérification, déploiement). |
Le saut décisif se fait entre L1 et L2. En L1, la provenance vaut une déclaration sur l’honneur : fort pratique pour un inventaire, sans valeur contre un attaquant. En L3, elle devient infalsifiable du point de vue du projet : même un mainteneur dont le compte est compromis ne peut pas faire signer à la plateforme un récit qui ne correspond pas au build réel.
Le schéma ci-dessous situe les menaces à chaque étape et montre ce que la piste Build couvre réellement :
À lire de haut en bas : la piste Build sécurise le passage par la plateforme, puis transfère la charge de la preuve au consommateur. Les deux premières et la troisième lignes restent la responsabilité d’autres mécanismes.
Attestation de provenance in-toto : contenu et signature
Section intitulée « Attestation de provenance in-toto : contenu et signature »La provenance SLSA est un document structuré au format in-toto (un cadre d’attestation de la chaîne logicielle, lui aussi projet open source). Une attestation in-toto se compose de trois couches :
- Statement : la liste des
subject, c’est-à-dire les artefacts concernés, identifiés par nom et condensat (par exemplesha256). C’est le condensat qui lie l’attestation à l’artefact, pas le nom de fichier ; - Predicate : le contenu typé. Pour SLSA 1.0, le
predicateTypevauthttps://slsa.dev/provenance/v1; - Enveloppe : en général DSSE (Dead Simple Signing Envelope), qui porte la signature sur le contenu sérialisé.
Le prédicat de provenance v1 contient deux blocs. buildDefinition décrit quoi : le buildType, les externalParameters (paramètres contrôlés par l’extérieur, typiquement le dépôt, la référence du workflow et le commit), les internalParameters et les resolvedDependencies. runDetails décrit qui et quand : le builder.id (l’identité de la plateforme de build), un identifiant d’exécution, les horodatages.
La règle qui fait tenir l’ensemble : la provenance doit être produite et signée par la plateforme, hors de portée des étapes que le projet contrôle. Si le script de build peut écrire l’attestation ou toucher la clé, le projet peut mentir, et un attaquant qui contrôle le projet aussi. C’est toute la différence entre L1 et L3.
Signature avec Sigstore
Section intitulée « Signature avec Sigstore »L’écosystème Sigstore fournit la signature dite « sans clé » utilisée par la plupart des générateurs de provenance :
- le job de CI (intégration continue) obtient un jeton OIDC (OpenID Connect) émis par la plateforme, qui atteste l’identité du workflow ;
- Fulcio, l’autorité de certification de Sigstore, échange ce jeton contre un certificat de courte durée (de l’ordre de dix minutes) qui encode cette identité ;
- la signature est inscrite dans Rekor, un journal de transparence en ajout seul, qui prouve qu’elle a existé pendant la validité du certificat.
L’avantage est de supprimer une clé longue durée à protéger. La contrepartie est moins souvent dite : la confiance se déplace vers l’émetteur OIDC de la plateforme et vers l’infrastructure Sigstore. Le détail des signatures d’artefacts et de commits est traité dans Signer ses commits et ses artefacts.
Vérifier la provenance avant installation et déploiement
Section intitulée « Vérifier la provenance avant installation et déploiement »Une provenance que personne ne vérifie est un fichier JSON de plus dans un bucket, ce qui fait un bel indicateur de conformité et zéro protection. Toute la valeur de SLSA se réalise au moment où un consommateur refuse un artefact.
La vérification qui compte porte sur quatre points, dans cet ordre :
- La signature est valide et chaîne vers une racine de confiance connue (racine Sigstore, ou clé de la plateforme).
- Le condensat de l’artefact figure dans les
subjectde l’attestation. - Le
builder.idattendu : la provenance a été émise par la plateforme et le workflow de confiance, pas par n’importe quel workflow. - Les paramètres externes attendus : bon dépôt source, bonne branche ou bonne étiquette.
Le piège classique est de s’arrêter au point 1. Une provenance signée par Sigstore depuis le dépôt d’un attaquant est parfaitement valide. N’importe qui peut obtenir une attestation authentique pour un artefact malveillant ; la seule chose qu’il ne peut pas faire, c’est la faire émettre au nom du dépôt et du workflow légitimes. Une vérification sans contrainte d’identité ne prouve donc qu’une chose : que l’attaquant sait utiliser une CI.
Le trajet complet, du commit au déploiement, avec les points où le refus doit tomber :
Ce qu’il faut y lire : la vérification est une étape bloquante entre le registre et l’environnement d’exécution, pas un rapport consulté après coup.
Politiques d’admission
Section intitulée « Politiques d’admission »Pour les conteneurs, la vérification s’automatise dans un contrôleur d’admission Kubernetes : Kyverno et le policy-controller de Sigstore savent tous deux exiger une attestation signée par une identité donnée avant d’accepter un pod. Trois règles d’architecture en découlent :
- déployer par condensat (
image@sha256:...), jamais par étiquette mutable : une étiquettev1.4peut pointer ailleurs entre la vérification et le tirage de l’image ; - commencer en mode audit, puis passer en mode bloquant par espace de noms : basculer tout un cluster d’un coup produit surtout une astreinte mémorable ;
- prévoir une procédure d’exception tracée (identité, motif, durée), faute de quoi la politique sera désactivée au premier incident à trois heures du matin.
Pour les écosystèmes de paquets, la logique est la même au moment de l’installation : npm publie des attestations de provenance (npm publish --provenance) que npm audit signatures contrôle, PyPI accepte des attestations liées à la publication de confiance. Les images de base méritent le même traitement, voir la généalogie des images de base Docker.
Exemple : vérifier une provenance SLSA en ligne de commande
Section intitulée « Exemple : vérifier une provenance SLSA en ligne de commande »Deux outils réels, chacun pour sa plateforme. Les chemins, dépôts et versions sont des valeurs d’exemple.
# Artefact publié avec slsa-github-generator (provenance .intoto.jsonl fournie avec la release).# slsa-verifier contrôle la signature, le condensat, le builder de confiance,# puis le dépôt et l'étiquette attendus. Sans --source-uri, la vérification n'a pas de sens.slsa-verifier verify-artifact outil-linux-amd64 \ --provenance-path outil-linux-amd64.intoto.jsonl \ --source-uri github.com/exemple-org/outil \ --source-tag v1.4.0
# Artefact attesté avec les "artifact attestations" de GitHub.# --repo restreint l'origine au dépôt attendu ; --owner seul accepterait# n'importe quel dépôt de l'organisation, ce qui est souvent trop large.gh attestation verify outil-linux-amd64 --repo exemple-org/outilUn code de retour non nul doit interrompre le pipeline de déploiement. Le contrôle s’insère comme étape bloquante, au même titre qu’un test en échec.
Ce que SLSA ne garantit pas
Section intitulée « Ce que SLSA ne garantit pas »La traçabilité dit d’où vient la viande, pas si la recette est bonne. Concrètement :
- La qualité et la sûreté du code : un artefact construit en Build L3 depuis un code vulnérable est un artefact vulnérable, parfaitement tracé. Ce terrain relève de la revue de code au-delà du linter et des tests SAST et DAST.
- Les dépendances : la provenance peut lister des
resolvedDependencies, sans rien affirmer de leur propre fabrication. Une bibliothèque compromise en amont est fidèlement intégrée et fidèlement attestée. Voir dépendances transitives. - La revue humaine et l’intégrité du dépôt : la piste Build ne vérifie ni qu’un changement a été relu à deux, ni que le compte qui a poussé n’est pas volé. Le scénario xz-utils (un mainteneur malveillant) passe sous les radars. Côté dépôt, voir les permissions Git en entreprise et les comptes de service jamais révoqués.
- La reproductibilité : SLSA atteste qu’une plateforme donnée a produit l’artefact. Il ne prouve pas qu’un tiers obtiendrait le même binaire. C’est le rôle des builds reproductibles, complémentaires et nettement plus coûteux.
SLSA et SBOM : origine contre composition
Section intitulée « SLSA et SBOM : origine contre composition »Le SBOM (Software Bill of Materials) dit ce qu’il y a dedans : composants, versions, licences, au format SPDX ou CycloneDX. La provenance SLSA dit d’où ça vient et comment ça a été fabriqué. L’un sans l’autre laisse un trou : un SBOM non attesté peut décrire un autre binaire que celui déployé. Le bon montage consiste à générer le SBOM dans le build attesté et à le publier comme attestation in-toto liée au même condensat, pour que composition et origine se vérifient ensemble.
Surface d’attaque et exploitation d’une chaîne SLSA
Section intitulée « Surface d’attaque et exploitation d’une chaîne SLSA »Atteindre un niveau ne fige rien. Les attaques connues contre un montage SLSA ciblent les hypothèses implicites :
- Empoisonnement de cache : un cache de build partagé entre workflows (dépendances, couches) peut être écrit par un job peu privilégié et relu par le job de release. C’est exactement la violation d’isolation que L3 interdit ; il faut séparer les caches du workflow de release ou s’en passer.
- Runners auto-hébergés persistants : une machine qui survit entre deux builds porte l’état du précédent. Pour viser L3, les runners doivent être éphémères, un par exécution.
- Déclencheurs dangereux : un workflow privilégié lancé sur du code de contributeur externe (le motif
pull_request_targetsur GitHub Actions) donne au code non relu l’accès aux secrets et aux jetons d’identité. - Vérification trop large : accepter « toute l’organisation » ou toute branche transforme n’importe quel dépôt secondaire en source d’artefacts de production.
- Actions et étapes tierces non épinglées : une action référencée par étiquette mutable change sous les pieds du build. Épingler par condensat de commit. Le durcissement général est détaillé dans sécuriser un pipeline CI/CD.
Côté exploitation, quatre postes à prévoir :
- Clés et rotation : avec Sigstore sans clé, les certificats expirent en quelques minutes et la racine est distribuée via TUF (The Update Framework). Il faut donc maintenir à jour la racine de confiance des vérificateurs, surtout en environnement isolé. Avec une plateforme qui signe par clé propre, cette clé relève d’un HSM (Hardware Security Module) ou d’un KMS (Key Management Service), avec une procédure de rotation et de publication de la nouvelle clé publique avant bascule.
- Supervision : surveiller le journal Rekor pour les signatures émises au nom de ses propres identités ; une entrée inattendue signale un workflow détourné. Journaliser et alerter sur chaque refus d’admission.
- Sauvegarde et reprise : les attestations doivent être stockées avec les artefacts (référents OCI dans le registre, fichiers de release), et non seulement chez un service tiers. Sans elles, un environnement restauré ne peut plus rien admettre.
- Révocation : une provenance ne se révoque pas. Retirer un artefact compromis passe par la politique de vérification (liste de condensats refusés, contrainte de version minimale), ce qu’il faut avoir prévu avant d’en avoir besoin.
Monter en niveau SLSA : une démarche réaliste
Section intitulée « Monter en niveau SLSA : une démarche réaliste »Le compromis central tient en une phrase : on gagne une provenance infalsifiable en confiant la fabrication à une plateforme qu’on ne contrôle plus entièrement. On paie en dépendance au fournisseur de build, en perte de souplesse (pas de build de release depuis un poste, plus de bricolage dans le workflow de publication) et en un nouveau point de rupture, la vérification bloquante.
La recommandation : viser directement Build L3 sur un générateur hébergé qui le fournit, et rendre la vérification bloquante avant de chercher à aller plus loin. Elle vaut tant que la plateforme hébergée est acceptable pour le code concerné (souveraineté, confidentialité). Dans le cas contraire, construire une plateforme L3 interne est un projet d’infrastructure à part entière, avec isolation et gestion de clés, à ne pas sous-estimer.
L’ordre qui fonctionne :
- Inventorier les artefacts réellement déployés et leur mode de fabrication actuel. Tout ce qui sort d’un poste développeur (voir les postes développeurs, cible oubliée) passe en premier dans un pipeline.
- Isoler un workflow de release dédié, sans cache partagé, avec runners éphémères et actions épinglées.
- Brancher un générateur de provenance existant (
slsa-github-generatorpour atteindre L3 sur GitHub Actions ; les attestations d’artefacts GitHub sont documentées comme L2 par défaut et L3 via workflows réutilisables). - Vérifier en mode audit côté déploiement, avec contrainte sur le dépôt et le builder.
- Basculer en bloquant, environnement par environnement, procédure d’exception comprise.
- Ajouter le SBOM attesté, puis traiter la source (revue obligatoire, protection de branches) et les dépendances.
S’arrêter à L1 sans vérification reste la pire option : elle coûte l’outillage et ne protège de rien, ce qui en fait la spécialité des tableaux de bord de maturité.
Faut-il attendre la piste Source pour adopter SLSA ?
Section intitulée « Faut-il attendre la piste Source pour adopter SLSA ? »Non. La piste Build traite la fabrication et la publication, qui sont attaquées indépendamment du dépôt. Les protections du dépôt (revue obligatoire, branches protégées, signature des commits) s’appliquent déjà sans attendre de label.
Une provenance SLSA remplace-t-elle la signature des artefacts ?
Section intitulée « Une provenance SLSA remplace-t-elle la signature des artefacts ? »Elle en est une forme enrichie : la provenance signée lie l’artefact par son condensat et ajoute le récit de fabrication. Une signature nue prouve qui a signé, pas comment l’objet a été construit.
Les builds reproductibles rendent-ils SLSA inutile ?
Section intitulée « Les builds reproductibles rendent-ils SLSA inutile ? »Non, ils répondent à une autre question. La reproductibilité permet à un tiers de recalculer le binaire ; SLSA atteste l’origine sans exiger ce recalcul. Les deux combinés donnent la garantie la plus forte, au prix le plus élevé.
🐝 Ce qui arrive si on s’en passe
Section intitulée « 🐝 Ce qui arrive si on s’en passe »Sans provenance attestée ni vérification, un artefact en production ne se rattache de façon prouvable à aucun commit ni à aucune exécution de build : seuls son nom et son étiquette le désignent. Si un runner, un cache ou un jeton de publication se révèle compromis, aucun moyen ne permet de délimiter les artefacts fabriqués pendant la fenêtre d’exposition. Le périmètre de l’incident s’étend alors à tout ce que la plateforme a produit, et la seule reprise sûre consiste à tout reconstruire et à tout redéployer depuis une source jugée saine. De même, un registre accepte un artefact poussé avec un jeton de publication volé sans qu’aucun contrôle en aval ne le distingue d’une release légitime. L’analyse post-incident perd enfin son point d’appui : rien ne relie l’empreinte d’un binaire suspect à l’exécution qui l’a produit.
🦫 Explication de la marmotte 🍫
Section intitulée « 🦫 Explication de la marmotte 🍫 »Un logiciel commence sous forme de texte écrit par des développeurs, rangé dans un dépôt. Une machine appelée plateforme de construction transforme ce texte en programme installable. Des pirates ont compris qu’il était plus discret d’attaquer cette machine que le texte : le programme final contient alors un piège, alors que le texte d’origine paraît propre. SLSA est une méthode qui oblige la machine de construction à rédiger, à chaque fabrication, une fiche d’origine : quel programme a été produit, à partir de quelle version exacte du texte, sur quelle machine, à quel moment. Le programme est désigné dans la fiche par une empreinte calculée sur son contenu ; changer un seul octet change l’empreinte. La machine signe ensuite cette fiche avec une signature numérique que le projet lui-même ne peut pas imiter. Plus le niveau est élevé, plus la fiche est difficile à falsifier. Avant d’installer le programme, l’entreprise qui le reçoit vérifie la signature, compare l’empreinte, et contrôle que la fiche vient bien du bon projet et de la bonne machine. Si un seul contrôle échoue, l’installation est refusée et une alerte part. Cette méthode a des limites : elle ne dit pas si le code est bien écrit, ni si les morceaux empruntés à d’autres projets sont sains, ni si quelqu’un a relu les modifications. Une autre liste, le SBOM, décrit les composants contenus dans le programme.
À lire aussi
- L'attaque de la chaîne d'approvisionnement logicielle en une pageComment une dépendance piégée traverse le build, reçoit une signature valide et s'installe chez tous les clients, en cinq étapes animées, avec SolarWinds, xz-utils, event-stream et les parades qui coupent la chaîne.
- Gérer les risques tiers et la chaîne logicielleCette page traite de la gestion des risques liés aux fournisseurs, dépendances et composants de la chaîne d'approvisionnement logicielle.
- Attaques supply chain et protection des dépendancesComprendre les attaques de chaîne d'approvisionnement logicielle, leurs vecteurs et les contrôles nécessaires sur les dépendances, builds et mises à jour.
- La chaîne d'approvisionnement logicielleUne application moderne exécute surtout du code que personne dans l'équipe n'a lu, écrit par des inconnus dont certains sont épuisés. SBOM, épinglage, signatures et constructions reproductibles réduisent réellement le risque, mais aucun ne dit si l'auteur est honnête : la porte dérobée de xz-utils l'a montré en passant à travers presque tous.
Pages voisines
La citent
- Sécuriser les mises à jour automatiques de dépendances et semver
- Formats, bibliothèques et API : rendre la crypto utilisable
SLSA : niveaux Build, provenance in-toto et vérification
Elle cite
- Lien dans les deux sens :Images Docker de base et confiance héritée
- Lien dans les deux sens :SBOM pour inventorier les composants réellement exécutés
- Lien dans les deux sens :Signer commits et artefacts contre quelles attaques
- Lien dans les deux sens :Protéger les branches Git et permissions entreprise
- Lien dans les deux sens :Sécuriser les secrets et permissions CI/CD
- Maîtriser le risque des dépendances transitives (npm, pip, Maven, Go)
- Pourquoi les builds reproductibles échouent souvent
- Comment revoir le code de sécurité au-delà du linter
- Comptes de service Git à révoquer réellement
- Durcir les postes de développeurs contre le vol de code et secrets
: les deux pages se citent l’une l’autre.
