Software Engineering 5 Min. Lesezeit

SPDX-Kaskaden verstehen: Wenn SBOMs aufeinander verweisen

Wie kaskadierende SPDX-Dokumente funktionieren: ExternalDocumentRef, Cross-Document-Relationships, Auflösung per Checksumme, Tücken realer Daten.

SPDX-Kaskaden verstehen: Wenn SBOMs aufeinander verweisen

SPDX-Kaskaden verstehen: Wenn SBOMs aufeinander verweisen

Kaskadierende SPDX-Dokumente sind der Teil des SBOM-Themas, über den kaum jemand schreibt und an dem in der Praxis die meisten Werkzeuge scheitern. Dabei ist das Muster in Delivery-Pipelines der Normalfall: Ein Release-SBOM beschreibt nicht jedes Paket selbst, sondern verweist auf die SBOMs seiner Komponenten, die wiederum auf die ihrer Container-Images zeigen. Beim Bau von SBOM Lens haben wir uns monatelang mit genau diesem Mechanismus beschäftigt. Dieser Artikel erklärt, wie die Verkettung technisch funktioniert und welche Fallstricke reale Dokumente mitbringen.

Warum überhaupt mehrere Dokumente?

Man könnte ein Release komplett in einem einzigen SPDX-Dokument beschreiben. In der Praxis scheitert das an Zuständigkeiten und Build-Zeitpunkten. Das Team einer Komponente erzeugt sein SBOM in der eigenen Pipeline, zum Zeitpunkt des Komponenten-Builds. Das Container-Image bekommt sein SBOM beim Image-Build, etwa von Syft oder Trivy. Das Release-SBOM entsteht zuletzt und soll die Teile zusammenführen, ohne sie zu duplizieren. Duplizieren wäre auch fachlich falsch: Die Komponenten-SBOMs sind signierte, versionierte Artefakte. Ein Release-Dokument, das ihren Inhalt kopiert, veraltet in dem Moment, in dem eine Komponente neu gebaut wird.

SPDX 2.x bildet das über zwei Bausteine ab: ExternalDocumentRef deklariert ein fremdes Dokument, Relationships verbinden Elemente über Dokumentgrenzen hinweg.

Der Mechanismus: ExternalDocumentRef plus Relationship

Ein Release-Dokument deklariert seine Referenzen im Kopf. Jede Referenz besteht aus einer lokalen ID, dem Namespace des Zieldokuments und einer Prüfsumme:

{
  "externalDocumentRefs": [
    {
      "externalDocumentId": "DocumentRef-billing-service",
      "spdxDocument": "https://example.org/spdxdocs/billing-service-2.4.1",
      "checksum": {
        "algorithm": "SHA1",
        "checksumValue": "d6a770ba38583ed4bb4525bd96e50461655d2759"
      }
    }
  ]
}

Die Verknüpfung selbst passiert in einer Relationship, die das fremde Element über das Präfix anspricht:

{
  "spdxElementId": "SPDXRef-Package-release",
  "relationshipType": "CONTAINS",
  "relatedSpdxElement": "DocumentRef-billing-service:SPDXRef-DOCUMENT"
}

Gelesen heißt das: Das Release-Paket enthält das Wurzelelement des Billing-Service-Dokuments. Ein Viewer, der die Kaskade auflösen will, muss also für jede Referenz das passende Dokument finden und die Element-IDs über die Präfixe hinweg auflösen. Klingt mechanisch, hat aber zwei interessante Detailfragen: Woran erkenne ich das richtige Dokument, und was tue ich, wenn es fehlt?

Auflösung: Checksumme schlägt Namespace

Der Namespace ist eine URI, aber niemand garantiert, dass sie auflösbar ist oder dass die Datei, die man lokal vorliegen hat, unter genau dieser URI erzeugt wurde. Verlässlicher ist die Prüfsumme: Sie identifiziert den exakten Dokumentstand, unabhängig von Dateiname und Ablageort. In SBOM Lens matchen wir deshalb zuerst über die SHA1-Prüfsumme aller geladenen Dateien und fallen erst danach auf den Namespace-Vergleich zurück. Die Reihenfolge ist keine Kosmetik. Wer zuerst über Namespaces matcht, verbindet im Zweifel ein Release mit einer veralteten Version des Komponenten-SBOMs, und genau solche stillen Fehler will man in einer Lieferketten-Analyse nicht haben.

Bleibt eine Referenz unaufgelöst, ist die schlechteste Reaktion ein leerer Knoten ohne Kontext. Besser ist ein expliziter Platzhalter, der zeigt, welches Dokument fehlt, und anbietet, es per URL zu laden oder eine Datei zuzuordnen. Fehlende Teile sind in einer Kaskade keine Ausnahme, sondern ein Zustand, mit dem das Tooling umgehen muss.

Die Tücken realer Dokumente

Die Spezifikation auf spdx.dev ist präzise. Die Dokumente, die Generatoren tatsächlich ausgeben, sind es nicht immer. Vier Muster begegnen uns wiederholt.

Erstens Prüfsummen-Schreibweisen: Manche Tools schreiben SHA1: abc..., andere SHA1:abc..., wieder andere variieren die Groß- und Kleinschreibung des Algorithmus. Zweitens doppelte SPDXIDs innerhalb eines Dokuments, meist ein Generator-Bug, der streng genommen das Dokument ungültig macht, praktisch aber ignorierbar ist. Drittens Versionen, die nicht im versionInfo-Feld stehen, sondern nur in der purl im externalRefs-Block stecken. Wer Versionskonflikte über eine Kaskade hinweg finden will, muss purls parsen, sonst sieht er nichts. Viertens Relationship-Typen außerhalb der Spezifikation, oft aus älteren Tool-Versionen.

Ein Parser hat hier zwei Optionen: streng ablehnen oder tolerant laden und die Befunde ausweisen. Für ein Analyse-Werkzeug ist nur die zweite Option brauchbar. Die NTIA-Minimum-Elements liefern dafür den passenden Prüfrahmen: Statt Dokumente abzulehnen, misst man, welche Pflichtfelder abgedeckt sind, und macht Lücken sichtbar.

Fazit

Kaskadierende SBOMs sind kein Exotenthema, sondern die logische Struktur arbeitsteiliger Delivery-Pipelines. Wer sie auswerten will, braucht drei Dinge: Auflösung per Prüfsumme vor Namespace, einen klaren Umgang mit fehlenden Dokumenten und Toleranz gegenüber den Macken realer Generatoren. Wie sich das anfühlt, wenn es funktioniert, lässt sich mit dem Beispiel-Datensatz in SBOM Lens in zwei Minuten ausprobieren. Und wenn Ihre Pipeline zwar SBOMs erzeugt, aber noch keine verwertbare Kaskadenstruktur, unterstützen wir beim Aufbau: Software Engineering bei EverBright.

Häufige Fragen

Was ist ein ExternalDocumentRef in SPDX?

ExternalDocumentRef ist der SPDX-Mechanismus, mit dem ein Dokument auf ein anderes verweist. Die Referenz besteht aus einer lokalen ID, dem Document Namespace des Ziels und einer Prüfsumme über die Zieldatei. Relationships können damit Elemente über Dokumentgrenzen hinweg verbinden, etwa ein Release-Paket mit dem SBOM einer Komponente.

Warum sollte man SBOM-Referenzen per Checksumme statt Namespace auflösen?

Die Prüfsumme identifiziert den exakten Stand eines Dokuments, während ein Namespace nur ein Name ist, der auf veraltete oder abweichende Dateien zeigen kann. Wer zuerst per Checksumme matcht, verhindert stille Fehlzuordnungen zwischen Release und Komponenten-SBOM, die bei Namespace-Matching unbemerkt bleiben können.

Wie geht man mit fehlenden Dokumenten in einer SBOM-Kaskade um?

Fehlende Referenzen sollten als explizite Platzhalter sichtbar bleiben statt still ignoriert zu werden. Gute Tools zeigen, welches Dokument fehlt, und bieten an, es per URL nachzuladen oder eine lokale Datei zuzuordnen. So bleibt die Analyse nutzbar und die Lücke dokumentiert, bis das fehlende SBOM verfügbar ist.

Sind kaskadierende SBOMs Pflicht?

Nein, keine Regulierung schreibt Kaskaden vor. Sie entstehen natürlich, sobald Komponenten in getrennten Pipelines gebaut werden und ihre SBOMs zum Build-Zeitpunkt erzeugt werden. Ein Release-Dokument verweist dann auf bestehende Artefakte, statt deren Inhalt zu kopieren, was Signaturen und Versionsstände intakt hält.

#SPDX #SBOM #ExternalDocumentRef #Supply Chain Security
Teilen:
Sergej Bardin

Sergej Bardin

CEO · KI-Strategie & IT-Beratung

Begleitet mittelständische Unternehmen bei KI-Adoption und Cloud-Strategie. Fokus auf praxistaugliche Entscheidungen statt Hype.

KI-StrategieMCPRAGMulti-CloudIT-BeratungMittelstand