SBOM pour les modules et binaires Go pour le CRA
Sur cette page
Le Cyber Resilience Act demande à chaque fabricant de tenir une nomenclature des logiciels « dans un format couramment utilisé et lisible par machine couvrant au moins les dépendances de niveau supérieur des produits » (annexe I, partie II, point 1). Go simplifie l’essentiel : les modules ont des versions exactes, et chaque binaire porte la liste des modules avec lesquels il a été construit. Il dispose aussi d’un outil officiel et gratuit pour savoir si une vulnérabilité atteint vraiment votre code.
Pour le règlement lui-même, voir Le SBOM pour le Cyber Resilience Act.
go.mod sert (presque) de fichier de verrouillage
Depuis Go 1.17, go.mod liste tous les modules nécessaires pour construire les paquets du module principal, les dépendances directes d’abord et les indirectes marquées // indirect, à des versions exactes. go.sum ne contient que des empreintes. Deux points à surveiller :
- Les directives
replaceremplacent un module par une variante ou un répertoire local. Le SBOM doit nommer ce qui est réellement compilé, pas le module d’origine. - La liste dépasse ce qui est compilé.
go.modcouvre tous les paquets du module, tests et outils compris. Un binaire construit à partir de./cmd/serverpeut utiliser bien moins de modules.
Produire le SBOM
cyclonedx-gomod, du projet CycloneDX, a trois modes. Pour un produit, utilisez app, qui ne suit que les paquets de l’application construite :
go install github.com/CycloneDX/cyclonedx-gomod/cmd/cyclonedx-gomod@latest
GOOS=linux GOARCH=amd64 cyclonedx-gomod app -json -std -main cmd/server -output sbom.cdx.json .
Donnez à GOOS, GOARCH et GOFLAGS=-tags=... les valeurs de votre build de publication : les contraintes de build changent les modules compilés. -std ajoute la bibliothèque standard de Go comme composant (voir plus bas). mod décrit tout le module, ce qui convient à une bibliothèque ; bin lit un binaire compilé.
Le binaire se décrit lui-même
Tout binaire Go construit avec les modules embarque ses informations de build :
go version -m ./server
affiche la version de Go, le module principal et chaque dépendance avec sa version et son empreinte. C’est ainsi que des scanners comme Syft, Trivy et govulncheck lui-même (-mode binary) peuvent décrire ou vérifier un binaire Go trouvé dans une image de conteneur ou sur un appareil, sans le code source.
La bibliothèque standard est un composant
Beaucoup de vulnérabilités Go se trouvent dans la bibliothèque standard : net/http, crypto/x509, html/template, os/exec. Votre binaire contient la bibliothèque standard de la version de Go qui l’a construit : cette version fait partie de votre produit et doit figurer dans le SBOM. Construisez vos versions avec une version de Go maintenue (chaque version majeure, comme 1.25, est maintenue jusqu’à la sortie de deux versions plus récentes), indiquez-la dans la ligne toolchain de go.mod, et construisez avec GOTOOLCHAIN fixé à cette version exacte, ou dans une image de build figée, pour que chaque build utilise la même : avec la valeur par défaut GOTOOLCHAIN=auto, un Go local plus récent l’emporte. go version -m enregistre la version réellement utilisée.
govulncheck : le code vulnérable est-il appelé ?
govulncheck, de l’équipe Go, construit le graphe d’appels de votre programme et ne signale que les vulnérabilités dont les fonctions vulnérables sont réellement atteignables depuis votre code :
go install golang.org/x/vuln/cmd/govulncheck@latest
govulncheck ./...
govulncheck -format openvex ./... > reach.vex.json
La sortie OpenVEX indique, pour chaque vulnérabilité connue des versions de modules avec lesquelles vous construisez, si votre code est concerné. C’est le genre de preuve qu’attend la gestion des vulnérabilités du CRA. Les appels par réflexion, par extensions ou par cgo ne sont pas vus, et l’analyse porte sur une plateforme et un jeu d’étiquettes de build à la fois. Regardez d’abord les vulnérabilités exploitées, et voyez Qu’est-ce que VEX ? pour la lecture des déclarations.
Ce que fait Provetry
Provetry lit go.mod, avec ses directives replace (son SBOM peut donc aussi lister des modules qui ne servent qu’aux tests ou aux outils), depuis votre CI ou dans les fichiers que vous envoyez, vérifie la version de Go de la ligne toolchain pour les avis de la bibliothèque standard, établit le SBOM de chaque version en CycloneDX, et en SPDX avec les offres payantes, et surveille chaque jour avec les offres payantes et chaque semaine avec l’offre gratuite chaque module pour les vulnérabilités nouvelles et exploitées. Son étape de CI lance govulncheck dans chaque module Go du dépôt : les vulnérabilités que votre code n’appelle jamais sont proposées comme « non concernées », avec la preuve de govulncheck ; celles qu’il appelle remontent en tête. Si govulncheck échoue dans un module, rien de ce dont ce module dépend n’est déclaré non concerné. Ce sont les seuls résultats sur lesquels s’appuie un contrôle bloquant en CI.