SBOM et sécurité de la supply chain logicielle : peut-on faire confiance à ses dépendances ?
Votre application, c'est avant tout du code écrit par d'autres. Voici comment les SBOM, la provenance signée et les contrôles à l'entrée vous disent en quelques minutes si la prochaine attaque supply chain vous concerne.
Par Innovation T Team
Une application en production contient bien plus de code écrit par des inconnus que par votre propre équipe. D'expérience, un service Node.js avec 30 dépendances directes embarque couramment plus d'un millier de paquets transitifs, et personne, absolument personne, ne les a lus. Quand le prochain épisode XZ Utils ou event-stream éclatera, les gagnants seront les équipes capables de répondre en quelques minutes à une seule question : exécutons-nous réellement la version affectée ?
L'iceberg des dépendances
Vous auditez votre code. Vous relisez les pull requests. Puis npm install exécute des scripts postinstall arbitraires venus d'un paquet enfoui six niveaux plus bas dans votre arbre, publié par quelqu'un dont le compte est protégé par un mot de passe de 2014. C'est toute l'asymétrie de la sécurité de la supply chain : vos contrôles couvrent les dix pour cent du code que vous avez écrits, et vos attaquants le savent.
Trois propriétés font des dépendances une surface d'attaque particulièrement redoutable :
- L'invisibilité transitive. Vous avez choisi
express. Vous n'avez pas choisi les dizaines de paquets qu'il traîne derrière lui, et personne d'autre dans votre équipe non plus. Sur la majorité de votre arbre, aucune décision de confiance n'a jamais été prise. - L'exécution à l'installation. Beaucoup d'écosystèmes exécutent des scripts de cycle de vie au moment de l'installation. Compromettez un paquet populaire et vous obtenez de l'exécution de code sur chaque poste de développeur et chaque runner CI qui le télécharge, avant même que l'application ne démarre.
- L'héritage de confiance. Le portable compromis d'un mainteneur, un domaine e-mail expiré ou un projet cédé à un repreneur deviennent votre incident. L'attaque event-stream a fonctionné exactement ainsi : un inconnu serviable a demandé les droits de publication sur un paquet abandonné, et les a obtenus.
Vous ne vous en sortirez pas par la revue de code. L'arbre est trop grand et il change chaque semaine. Ce que vous pouvez construire, en revanche, ce sont trois couches : l'inventaire (savoir ce que vous livrez), la vérification (prouver d'où cela vient) et les contrôles à l'entrée (ralentir et assainir ce qui entre). Le SBOM est la couche d'inventaire, et tout le reste s'appuie dessus.
Ce qu'est réellement un SBOM
Un Software Bill of Materials est un inventaire exploitable par machine de chaque composant d'un artefact précis : nom du paquet, version exacte, fournisseur, empreintes cryptographiques, licence et relations de dépendance entre composants. Pas un tableur. Pas votre package.json, qui liste des intentions plutôt que des résolutions. Un document structuré, rattaché à un build concret.
Deux formats dominent, et le choix est bien moins dramatique que ne le suggèrent les forums :
- SPDX (ISO/IEC 5962). Le doyen. Le plus solide historiquement sur la conformité des licences, un outillage large, privilégié dans les écosystèmes de la Linux Foundation.
- CycloneDX (issu de l'OWASP, désormais normalisé ECMA-424). Conçu pour les workflows de sécurité. Support natif des références de vulnérabilités, du VEX, des services, des composants matériels et ML. Si votre cas d'usage principal est la réponse aux vulnérabilités, commencez par lui.
Les deux se sérialisent en JSON. Les deux se convertissent l'un vers l'autre avec une fidélité acceptable. Choisissez-en un, générez-le de façon systématique, et refusez que le débat de format retarde le déploiement.
La réglementation pousse fort dans cette direction. Aux États-Unis, les achats fédéraux exigent des SBOM depuis l'Executive Order 14028. Côté européen, le Cyber Resilience Act étend des obligations comparables à quasiment quiconque commercialise des produits comportant des éléments numériques sur le marché de l'Union, éditeurs tunisiens ou suisses exportant vers l'UE compris. Et n'oubliez pas le RGPD : une dépendance compromise qui exfiltre des données personnelles constitue une violation de données au sens de l'article 33, avec 72 heures pour notifier la CNIL ou votre autorité de contrôle, ce qui suppose de savoir très vite ce que vous exécutez. Si vous vendez du logiciel, les clauses SBOM arrivent dans vos contrats, que vous vous y prépariez ou non. Vous préparer coûte moins cher.
Générez au moment du build, pas à la demande
Le mode d'échec le plus courant : générer un SBOM chaque trimestre à partir d'un scan des sources et considérer la case cochée. Un SBOM déconnecté d'un artefact de build précis est une supposition avec une extension de fichier. Les règles qui comptent :
- Un SBOM par artefact, par build. Le SBOM de
api:1.4.2décrit exactement cette image, lockfile résolu inclus. - Scannez l'artefact, pas seulement les sources. Une image de conteneur contient des paquets OS (apk, deb, rpm), des dépendances applicatives et des binaires isolés que quelqu'un a copiés dedans. Un scan des sources ne voit rien de la première catégorie et rate entièrement la troisième.
- Stockez les SBOM avec la release et gardez-les interrogeables. Leur valeur se démultiplie quand vous pouvez chercher d'un coup dans toutes les versions déployées.
Avec Syft, chaque mode de génération tient en une commande :
# Répertoire source, en s'appuyant sur le lockfile
syft dir:. -o cyclonedx-json > sbom.cdx.json
# Image de conteneur construite, paquets OS et binaires inclus
syft registry:ghcr.io/acme/api:1.4.2 -o cyclonedx-json > sbom-image.cdx.json
Attachez ensuite le SBOM à l'image sous forme d'attestation signée, afin que les consommateurs puissent vérifier qu'il a été produit par votre pipeline et non retouché après coup :
cosign attest --predicate sbom-image.cdx.json \
--type cyclonedx ghcr.io/acme/api:1.4.2
Là où la fiabilité d'un SBOM se dégrade en silence
Chaque générateur a ses angles morts. Connaissez les vôtres :
- Le code vendorisé ou copié. Une fonction reprise d'un article de blog ou une bibliothèque recopiée en dur n'a aucune identité de paquet. Elle n'apparaîtra pas.
- Les binaires statiques. Les binaires Go embarquent des informations de build lisibles par les outils. Un binaire C strippé est une boîte noire avec un nom de fichier.
- Le code frontend bundlé. Après le passage de webpack ou esbuild, l'artefact est un blob minifié. Générez le SBOM depuis le lockfile avant le bundling, puis livrez les deux.
- Les jars shadés du monde JVM renomment les paquets en interne et mettent en échec toute correspondance naïve.
Un SBOM qui revendique une exhaustivité qu'il n'a pas est pire que pas de SBOM du tout, parce qu'on lui fait confiance. Documentez précisément ce que votre étape de génération couvre et ce qu'elle ne peut pas voir.
De l'inventaire aux réponses
Le retour sur investissement arrive le jour où une CVE sérieuse tombe. Sans SBOM, vous devez reconstruire et rescanner chaque service pour savoir si vous êtes exposé, ce qui prend des jours dont vous ne disposez pas. Avec des SBOM archivés, vous interrogez des documents :
grype sbom:./sbom-image.cdx.json --fail-on high
Mieux encore : chargez chaque SBOM de release dans un serveur Dependency-Track. Il réévalue en continu votre inventaire existant face aux nouveaux avis de sécurité. Quand la prochaine faille de calibre Log4Shell atterrira, vous obtiendrez la liste des services affectés en quelques minutes, sans toucher au moindre build. Cette différence de vitesse fait toute la partie pendant un incident, et elle s'articule directement avec le travail de processus décrit dans notre playbook de réponse à incident.
Attendez-vous à du bruit. Un scanner appliqué à un SBOM signale des versions vulnérables que votre code n'exerce jamais. C'est exactement la raison d'être du VEX (Vulnerability Exploitability eXchange) : une déclaration lisible par machine, publiée aux côtés du SBOM, qui consigne votre analyse :
{
"@context": "https://openvex.dev/ns/v0.2.0",
"statements": [{
"vulnerability": { "name": "CVE-2026-XXXXX" },
"products": [{ "@id": "pkg:oci/api@sha256%3A3d1f..." }],
"status": "not_affected",
"justification": "vulnerable_code_not_in_execute_path"
}]
}
Les équipes qui font l'impasse sur le VEX se noient sous les alertes, finissent par ignorer le scanner et se retrouvent dans une situation pire qu'avant son installation. Le triage n'est pas une surcharge optionnelle. C'est le produit.
Ce qu'un SBOM ne détectera jamais
Soyez lucide sur les limites, car les éditeurs commerciaux ne le seront pas à votre place. Un SBOM est un inventaire de composants connus. Il ne protège en rien contre :
- Les paquets malveillants sans CVE. Un typosquat ou une release fraîchement piégée est "propre" tant que personne ne l'a découverte. Votre SBOM la listera fidèlement, sans lever la moindre alarme.
- La compromission du système de build. SolarWinds a livré des builds empoisonnés à partir d'une liste de dépendances irréprochable. Le malware est entré pendant la compilation, en dessous de la couche que décrit n'importe quel SBOM.
- Le détournement du compte d'un mainteneur qui publie, par le canal officiel, une release corrective d'apparence tout à fait légitime.
Combler ces failles exige de la provenance et des contrôles à l'entrée, pas davantage d'inventaire.
Exigez la provenance. Une preuve cryptographique de l'origine d'un artefact et du pipeline qui l'a construit. SLSA fournit le modèle de maturité, Sigstore fournit l'outillage. Concrètement : publiez vos propres paquets avec npm publish --provenance, vérifiez les images tierces avec cosign verify contre l'identité CI de l'éditeur, et traitez tout artefact non signé venant d'un fournisseur critique comme un constat d'audit à faire remonter.
Épinglez par contenu, pas par nom. Les noms et les tags sont déplaçables. Les digests ne le sont pas :
# GitHub Actions : épingler un SHA de commit, pas un tag que l'on peut repointer
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683
# Épingler les images de base par digest
FROM node:22-slim@sha256:3d1f9a...
Ralentissez la voie d'entrée. La plupart des versions malveillantes sont détectées et retirées dans les jours qui suivent leur publication. Un délai de carence transforme la vigilance de la communauté en protection pour vous :
{
"extends": ["config:recommended"],
"minimumReleaseAge": "7 days",
"internalChecksFilter": "strict"
}
Avec cette configuration Renovate, une release détournée doit survivre à une semaine d'examen public avant même que vos bots ne la proposent. Le coût : des dépendances légèrement moins fraîches. Le bénéfice : vous cessez d'être la victime précoce qui découvre la compromission pour tout le monde.
Neutralisez les scripts d'installation. Exécuter npm ci --ignore-scripts en CI supprime la primitive d'exécution la plus courante, au prix d'une liste blanche occasionnelle pour les paquets qui ont réellement besoin d'une étape de build. D'expérience, le compromis vaut d'être généralisé partout, postes de développeurs compris.
Un déploiement en 30 jours qui tient dans la durée
L'ordre a son importance. L'inventaire avant le blocage, le blocage avant la signature. Les équipes qui commencent par les signatures en négligeant les lockfiles bâtissent une cathédrale sur du sable.
- Jours 1 à 3 : discipline des lockfiles. Chaque dépôt versionne ses lockfiles. La CI installe avec
npm ci,pip install --require-hashesou l'équivalent de l'écosystème, et échoue en cas de dérive. - Jours 4 à 7 : générer les SBOM en CI. Ajoutez Syft aux pipelines de vos cinq services les plus critiques. CycloneDX JSON, un SBOM par artefact construit, stocké avec la release.
- Jours 8 à 12 : déployer Dependency-Track. Ingestion automatique de chaque SBOM. Routez les alertes vers le canal que votre astreinte lit réellement.
- Jours 13 à 17 : établir la base de référence et trier. Le premier scan sera laid. Classez chaque constat : exploitable maintenant, mise à niveau à planifier, ou non affecté (rédigez la déclaration VEX pendant que l'analyse est fraîche).
- Jours 18 à 22 : verrouiller le pipeline. Faites échouer les builds sur toute nouvelle vulnérabilité critique avec exploit connu. Ne bloquez pas sur le stock historique, sinon l'équipe contournera la barrière en moins d'un mois.
- Jours 23 à 26 : épingler et vérifier. Actions CI épinglées par SHA, images de base épinglées par digest. Activez la vérification de provenance pour vos fournisseurs les plus critiques.
- Jours 27 à 30 : ajouter le délai de carence. Renovate ou Dependabot avec un âge minimal de release, plus
--ignore-scriptsdans chaque job CI.
Tout cela vit à l'intérieur de votre chaîne de livraison, et c'est pourquoi le sujet appartient à la même conversation que le reste de vos contrôles. Nos guides sur le pipeline DevSecOps et les pipelines CI/CD auxquels les équipes font confiance couvrent la mécanique environnante.
Quel niveau de rigueur vous faut-il vraiment ?
Toutes les équipes n'ont pas besoin du niveau 3 de SLSA. La grille que nous appliquons avec nos clients :
- Vous vendez du logiciel ou des API à des grands comptes ou à des acheteurs régulés. Programme complet : SBOM par release, Dependency-Track, VEX, provenance signée. Les services achats exigeront bientôt ces documents, et "nous pourrons en générer un le trimestre prochain" fait perdre des appels d'offres.
- Vous opérez un SaaS pour des clients plus petits. Génération de SBOM, scan continu, discipline des lockfiles et délai de carence. Repoussez le VEX jusqu'à ce que le bruit du scanner devienne un coût mesurable.
- Outils internes, petite équipe. Lockfiles,
osv-scanneren CI, actions épinglées par SHA. Environ une heure de mise en place pour l'essentiel de la réduction de risque disponible. - Vous intégrez beaucoup de code généré par IA. Ajoutez une validation humaine spécifiquement sur l'introduction de nouvelles dépendances. Les LLM hallucinent des noms de paquets plausibles, des squatteurs enregistrent ces noms, et le slopsquatting est désormais un vecteur d'entrée bien réel.
Le fil conducteur : les contrôles sur la voie d'entrée sont peu coûteux et durables. L'analyse après coup est chère et toujours en retard. La confiance dans votre arbre de dépendances doit se gagner par des preuves, jamais se présumer, exactement le principe que le zero trust applique à la couche réseau.
Comment Innovation T peut vous aider
Innovation T construit et opère cette mécanique pour des équipes en Europe et en Afrique francophone : génération de SBOM câblée dans la CI, déploiements Dependency-Track qui survivent au contact du volume d'alertes réel, provenance signée, et politiques d'entrée réglées pour que les développeurs restent rapides pendant que les attaquants ralentissent. Nous menons le déploiement en 30 jours ci-dessus comme une mission à périmètre fixe, puis nous vous remettons un pipeline que votre équipe maintient vraiment.
Si un client vient de vous demander un SBOM, ou si vous êtes simplement incapable de répondre en moins d'une heure à la question "exécutons-nous la version affectée", parlons-en. Découvrez nos services ou contactez-nous pour une évaluation de maturité supply chain.
Prêt à construire avec Innovation T ?
Qu'il s'agisse de sécurité, de croissance ou d'ingénierie, notre équipe peut vous aider à livrer dans les meilleures conditions.