SBOM für Go-Module und -Binaries nach dem CRA
Auf dieser Seite
Der Cyber Resilience Act verlangt von jedem Hersteller eine Software-Stückliste in einem gängigen, maschinenlesbaren Format, die mindestens die Abhängigkeiten der obersten Ebene des Produkts erfasst (Anhang I Teil II Nummer 1). Go macht das meiste davon leicht: Module haben exakte Versionen, und jedes Binary trägt die Liste der Module, aus denen es gebaut wurde. Außerdem gibt es ein offizielles, kostenloses Werkzeug, das sagt, ob eine Schwachstelle Ihren Code tatsächlich erreicht.
Zur Verordnung selbst siehe SBOM für den Cyber Resilience Act.
go.mod ist (fast) die Lock-Datei
Seit Go 1.17 listet go.mod jedes Modul, das zum Bauen der Pakete des Hauptmoduls nötig ist, direkte Anforderungen zuerst und indirekte mit // indirect markiert, in exakten Versionen. go.sum enthält nur Prüfsummen. Zwei Punkte verdienen Aufmerksamkeit:
replace-Direktiven tauschen ein Modul gegen einen Fork oder ein lokales Verzeichnis. Die SBOM muss nennen, was tatsächlich gebaut wird, nicht das ursprüngliche Modul.- Es steht mehr darin, als gebaut wird.
go.moddeckt jedes Paket des Moduls ab, Tests und Werkzeuge eingeschlossen. Ein aus./cmd/servergebautes Binary nutzt womöglich weit weniger Module.
Die SBOM erzeugen
cyclonedx-gomod aus dem CycloneDX-Projekt hat drei Modi. Für ein Produkt verwenden Sie app, das nur den Paketen der Anwendung folgt, die Sie bauen:
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 .
Setzen Sie GOOS, GOARCH und GOFLAGS=-tags=... auf die Werte Ihres Release-Builds, denn Build-Constraints ändern, welche Module einkompiliert werden. -std fügt die Go-Standardbibliothek als Komponente hinzu (siehe unten). mod beschreibt das ganze Modul, was zu einer Bibliothek passt; bin liest ein kompiliertes Binary.
Das Binary beschreibt sich selbst
Jedes mit Modulen gebaute Go-Binary bettet seine Build-Informationen ein:
go version -m ./server
gibt die Go-Version, das Hauptmodul und jede Abhängigkeit mit Version und Prüfsumme aus. So können Scanner wie Syft, Trivy und govulncheck selbst (-mode binary) ein Go-Binary in einem Container-Image oder auf einem Gerät beschreiben oder prüfen, ohne den Quelltext.
Die Standardbibliothek ist eine Komponente
Viele Go-Schwachstellen liegen in der Standardbibliothek: net/http, crypto/x509, html/template, os/exec. Ihr Binary enthält die Standardbibliothek der Go-Version, die es gebaut hat, also gehört diese Version zu Ihrem Produkt und muss in die SBOM. Bauen Sie Versionen mit einer unterstützten Go-Version (jede Hauptversion, etwa 1.25, wird unterstützt, bis zwei neuere erschienen sind), setzen Sie die Zeile toolchain in go.mod und bauen Sie mit GOTOOLCHAIN auf genau dieser Version oder in einem fest gepinnten Builder-Image, damit jeder Build dieselbe nutzt: Mit dem Standard GOTOOLCHAIN=auto gewinnt ein neueres lokales Go. go version -m hält die tatsächlich verwendete Version fest.
govulncheck: Wird der verwundbare Code aufgerufen?
Das govulncheck des Go-Teams baut den Aufrufgraphen Ihres Programms und meldet nur die Schwachstellen, deren verwundbare Funktionen Ihr Code tatsächlich erreichen kann:
go install golang.org/x/vuln/cmd/govulncheck@latest
govulncheck ./...
govulncheck -format openvex ./... > reach.vex.json
Die OpenVEX-Ausgabe hält für jede bekannte Schwachstelle in den Modulversionen, mit denen Sie bauen, fest, ob Ihr Code betroffen ist. Das ist die Art von Nachweis, die die Schwachstellenbehandlung des CRA verlangt. Aufrufe über Reflection, Plugins oder cgo werden nicht erkannt, und pro Lauf wird eine Plattform mit einer Auswahl von Build-Tags analysiert. Schauen Sie zuerst auf die in freier Wildbahn ausgenutzten Schwachstellen, und lesen Sie Was ist VEX?, um zu sehen, wie solche Aussagen gelesen werden.
Wie Provetry hilft
Provetry liest go.mod mit seinen replace-Direktiven (seine SBOM kann daher auch Module aufführen, die nur Tests oder Werkzeuge nutzen) aus Ihrer CI oder aus den hochgeladenen Dateien, prüft die Go-Version der Zeile toolchain auf Sicherheitshinweise zur Standardbibliothek, schreibt die SBOM jeder Version in CycloneDX, in den kostenpflichtigen Tarifen auch in SPDX, und überwacht jedes Modul auf neue und ausgenutzte Schwachstellen, täglich in den kostenpflichtigen Tarifen und wöchentlich im kostenlosen. Sein CI-Schritt führt govulncheck in jedem Go-Modul des Repositorys aus: Schwachstellen, die Ihr Code nie aufruft, werden mit dem Nachweis von govulncheck als „nicht betroffen“ vorgeschlagen; die aufgerufenen rücken in der Liste nach oben. Scheitert govulncheck in einem Modul, wird nichts, wovon dieses Modul abhängt, als nicht betroffen erklärt. Nur auf diese Ergebnisse stützt sich ein CI-Gate.