← Terug naar blog

Waarom je SBOM faalt op PURL-validatie voor npm-pakketten met scope

· Verimu
PURLCycloneDXNTIASBOMnpm

Als je CycloneDX SBOM's genereert voor Node.js-projecten, heb je mogelijk gezien dat je SBOM schemavalidatie doorstaat maar faalt op de NTIA-minimumelementcontroles met deze fout:

Component requires at least one valid identifier (PURL or CPE). Both are currently missing or invalid. Path: components.pkg:npm/@types/node@20.11.5.identifiers Rule: Component.identifiers

Het component is er. De versie is er. De PURL lijkt correct: pkg:npm/@types/node@20.11.5. Dus wat is er mis?

Het probleem: twee @-tekens

Een Package URL (PURL) gebruikt het @-karakter als versieseparator. Het formaat is:

pkg:<type>/<namespace>/<n>@<version>

Wanneer je pkg:npm/@types/node@20.11.5 schrijft, staan er twee @-karakters in de string. Een PURL-parser moet weten welke de versie scheidt. Is het @types/node op versie 20.11.5, of is het @types/node@20.11.5 zonder versie?

Deze ambiguïteit zorgt ervoor dat PURL-parsers de identificator volledig afwijzen. Je component heeft feitelijk geen geldige PURL, wat betekent dat het niet voldoet aan het NTIA-vereiste voor een "uniek identificatienummer".

De specificatie is expliciet

De PURL-specificatie voor npm-pakketten behandelt dit geval direct:

"Het @-teken als prefix voor npm-scope wordt altijd procentgecodeerd, zoals dat was in de begindagen van npm-scopes."

De correcte codering voor npm-pakketten met scope is:

Pakket ❌ Onjuiste PURL ✅ Correcte 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

Het @ van de scope wordt %40, waardoor er precies één letterlijk @-teken in de hele PURL overblijft — ondubbelzinnig de versieseparator.

Pakketten zonder scope zoals express@4.18.2 worden niet beïnvloed: pkg:npm/express@4.18.2 is al correct.

Waarom deze fout zo vaak voorkomt

Het is een natuurlijke fout. Wanneer je naar @types/node kijkt, is het @-prefix onderdeel van hoe npm het pakket weergeeft en ernaar verwijst. Elke ontwikkelaar typt npm install @types/node — met het letterlijke @. Het coderen ervan voelt verkeerd.

De verwarring wordt vergroot doordat sommige PURL-voorbeelden op het internet (en zelfs in sommige CycloneDX-voorbeeldbestanden) het @-teken ongecodeerd tonen. De canonieke specificatievoorbeelden op GitHub tonen pkg:npm/@angular/animation@12.3.1 — maar de normatieve tekst in datzelfde document zegt dat het @ gecodeerd moet worden. De specificatietekst gaat voor.

De oplossing

Als je SBOM-tooling bouwt, is de oplossing eenvoudig. Bij het construeren van een PURL voor een npm-pakket met scope, codeer je het eerste @ 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}`;
}

Een veelgemaakte fout is het gebruik van een generiek name.replace('/', '%2F') of encodeURIComponent op de hele naam. Doe dat ook niet — de / tussen namespace en naam is een structureel PURL-scheidingsteken en moet ongecodeerd blijven.

Een snelle manier om te verifiëren

Na het corrigeren van je PURL-generatie kun je je SBOM valideren met:

Beide zullen ongeldige PURL's detecteren voordat ze een complianceprobleem worden.

Na de correctie

Met het scope-prefix @ correct procentgecodeerd, hebben je npm-pakketten met scope geldige PURL's en slaagt de NTIA-identificatorcontrole probleemloos:

✓ 12/12 NTIA-minimumelementcontroles geslaagd

Hoe Verimu dit aanpakt

De SBOM-generator van Verimu codeert npm-PURL's met scope correct volgens de PURL-specificatie — %40 voor het scope-prefix, ongecodeerde / voor het namespacescheidingsteken. Elk SBOM dat we genereren slaagt direct voor NTIA-minimumelementvalidatie.

Als je werkt aan CRA-compliance voor toegang tot de Europese markt, of je gewoon SBOM's wilt die niet falen op validatie in productie, hebben wij deze randgevallen al opgelost zodat jij dat niet hoeft te doen.

Start gratis → of boek een demo om Verimu in actie te zien.