Warum Ihr SBOM die PURL-Validierung für scoped npm-Pakete nicht besteht
Wenn Sie CycloneDX SBOMs für Node.js-Projekte generieren, haben Sie möglicherweise festgestellt, dass Ihr SBOM die Schema-Validierung besteht, aber bei den NTIA-Mindestanforderungsprüfungen mit diesem Fehler durchfällt:
Die Komponente ist vorhanden. Die Version ist vorhanden. Die PURL sieht richtig aus: pkg:npm/@types/node@20.11.5. Was also ist falsch?
Das Problem: zwei @-Zeichen
Eine Package URL (PURL) verwendet das @-Zeichen als Versions-Trennzeichen. Das Format ist:
pkg:<type>/<namespace>/<n>@<version>
Wenn Sie pkg:npm/@types/node@20.11.5 schreiben, gibt es zwei @-Zeichen im String. Ein PURL-Parser muss wissen, welches die Version abtrennt. Ist es @types/node in Version 20.11.5, oder ist es @types/node@20.11.5 ohne Version?
Diese Mehrdeutigkeit führt dazu, dass PURL-Parser den Bezeichner komplett ablehnen. Ihre Komponente hat effektiv keine gültige PURL, was bedeutet, dass sie die NTIA-Anforderung „Unique Identifier" nicht erfüllt.
Die Spezifikation ist eindeutig
Die PURL-Spezifikation für npm-Pakete adressiert dies direkt:
„Das npm-Scope-@-Zeichen-Präfix wird immer prozent-kodiert, wie es in den frühen Tagen von npm Scope der Fall war."
Die korrekte Kodierung für scoped npm-Pakete ist:
| Paket | ❌ Falsche PURL | ✅ Korrekte PURL |
|---|---|---|
@types/node@20.11.5 |
pkg:npm/@types/node@20.11.5 |
pkg:npm/%40types/node@20.11.5 |
@angular/core@17.1.0 |
pkg:npm/@angular/core@17.1.0 |
pkg:npm/%40angular/core@17.1.0 |
@vue/reactivity@3.4.1 |
pkg:npm/@vue/reactivity@3.4.1 |
pkg:npm/%40vue/reactivity@3.4.1 |
Das @ im Scope wird zu %40, sodass genau ein literales @ in der gesamten PURL verbleibt — eindeutig das Versions-Trennzeichen.
Unscoped Pakete wie express@4.18.2 sind nicht betroffen: pkg:npm/express@4.18.2 ist bereits korrekt.
Warum dieser Fehler so häufig vorkommt
Es ist ein natürlicher Fehler. Wenn man @types/node sieht, ist das @-Präfix Teil der Art, wie npm das Paket anzeigt und referenziert. Jeder Entwickler tippt npm install @types/node — mit dem literalen @. Es fühlt sich falsch an, es zu kodieren.
Zur Verwirrung beiträgt, dass einige PURL-Beispiele im Internet (und sogar in manchen CycloneDX-Beispieldateien) das @-Zeichen unkodiert zeigen. Die kanonischen Spec-Beispiele auf GitHub zeigen pkg:npm/@angular/animation@12.3.1 — aber der normative Text in demselben Dokument sagt, dass das @ kodiert werden muss. Der Spec-Text hat Vorrang.
Die Lösung
Wenn Sie SBOM-Werkzeuge entwickeln, ist die Lösung einfach. Beim Erstellen einer PURL für ein scoped npm-Paket kodieren Sie das führende @ als %40:
function buildPurl(name: string, version: string): string {
if (name.startsWith('@')) {
return `pkg:npm/%40${name.slice(1)}@${version}`;
}
return `pkg:npm/${name}@${version}`;
}
Ein häufiger Fehler ist die pauschale Verwendung von name.replace('/', '%2F') oder encodeURIComponent auf den gesamten Namen. Das sollten Sie auch nicht tun — der / zwischen Namespace und Name ist ein strukturelles PURL-Trennzeichen und muss unkodiert bleiben.
Eine schnelle Möglichkeit zur Überprüfung
Nach der Korrektur Ihrer PURL-Generierung können Sie Ihr SBOM mit folgenden Tools validieren:
- FOSSA NTIA SBOM Validator
- Der
purl-spec-Referenz-Parser auf GitHub
Beide erkennen ungültige PURLs, bevor sie zu einem Compliance-Problem werden.
Nach der Korrektur
Mit korrekt prozent-kodiertem @-Scope-Präfix tragen Ihre scoped npm-Pakete gültige PURLs und die NTIA-Identifier-Prüfung wird sauber bestanden:
Wie Verimu das handhabt
Verimis SBOM-Generator kodiert scoped npm-PURLs korrekt gemäß der PURL-Spezifikation — %40 für das Scope-Präfix, unkodiertes / für das Namespace-Trennzeichen. Jedes von uns generierte SBOM besteht die NTIA-Mindestanforderungsvalidierung sofort.
Wenn Sie auf CRA-Compliance für den EU-Marktzugang hinarbeiten, oder einfach SBOMs wollen, die nicht in der Produktion die Validierung nicht bestehen, haben wir diese Randfälle bereits gelöst, damit Sie es nicht müssen.
Kostenlos starten → oder Demo buchen, um Verimu in Aktion zu sehen.