SBOM
SBOM-eksempler
Den raskeste måten å forstå en SBOM på er å lese en. Her er den samme lille applikasjonen i CycloneDX og i SPDX, med hva hvert felt betyr, hvordan en svak SBOM ser ut og hvordan du sjekker din egen.
Oppdatert
Applikasjonen i disse eksemplene
Begge filene beskriver example-api 2.4.0, en illustrerende Node.js-tjeneste med én direkte avhengighet,
express. Express er i sin tur avhengig av accepts, så eksemplene viser også én transitiv
avhengighet. En ekte SBOM av en Express-applikasjon viser mange flere komponenter, men strukturen er den samme.
SBOM-eksempel i CycloneDX
{
"bomFormat": "CycloneDX",
"specVersion": "1.6",
"serialNumber": "urn:uuid:3e671687-395b-41f5-a30f-a58921a69b79",
"version": 1,
"metadata": {
"timestamp": "2026-10-30T09:00:00Z",
"lifecycles": [{ "phase": "build" }],
"tools": {
"components": [
{ "type": "application", "name": "example-sbom-tool", "version": "1.0.0" }
]
},
"component": {
"type": "application",
"bom-ref": "example-api",
"name": "example-api",
"version": "2.4.0"
}
},
"components": [
{
"type": "library",
"bom-ref": "pkg:npm/[email protected]",
"name": "express",
"version": "4.21.2",
"purl": "pkg:npm/[email protected]",
"licenses": [{ "license": { "id": "MIT" } }]
},
{
"type": "library",
"bom-ref": "pkg:npm/[email protected]",
"name": "accepts",
"version": "1.3.8",
"purl": "pkg:npm/[email protected]",
"licenses": [{ "license": { "id": "MIT" } }]
}
],
"dependencies": [
{ "ref": "example-api", "dependsOn": ["pkg:npm/[email protected]"] },
{ "ref": "pkg:npm/[email protected]", "dependsOn": ["pkg:npm/[email protected]"] }
]
}
| Felt | Hva det forteller deg |
|---|---|
specVersion |
Hvilken versjon av formatet filen bruker, slik at verktøy kan lese den. |
serialNumber, version |
Hvilken SBOM dette er, og hvilken revisjon av den. |
metadata.lifecycles |
Når SBOM-en ble laget. Her: under bygget. |
metadata.tools |
Hvilket verktøy som produserte den. To verktøy kan rapportere samme commit forskjellig. |
metadata.component |
Produktet SBOM-en beskriver. |
purl |
Package URL-en, identifikatoren som lar et verktøy matche komponenten mot advisories. |
licenses |
Komponentens deklarerte lisens. |
dependencies |
Hvem som trekker inn hvem. Det er dette som gjør accepts synlig som en transitiv avhengighet. |
SBOM-eksempel i SPDX
{
"spdxVersion": "SPDX-2.3",
"dataLicense": "CC0-1.0",
"SPDXID": "SPDXRef-DOCUMENT",
"name": "example-api-2.4.0",
"documentNamespace": "https://example.com/spdx/example-api-2.4.0",
"creationInfo": {
"created": "2026-10-30T09:00:00Z",
"creators": ["Tool: example-sbom-tool-1.0.0"]
},
"packages": [
{
"name": "example-api",
"SPDXID": "SPDXRef-Package-example-api",
"versionInfo": "2.4.0",
"downloadLocation": "NOASSERTION"
},
{
"name": "express",
"SPDXID": "SPDXRef-Package-express",
"versionInfo": "4.21.2",
"downloadLocation": "NOASSERTION",
"licenseDeclared": "MIT",
"externalRefs": [
{
"referenceCategory": "PACKAGE-MANAGER",
"referenceType": "purl",
"referenceLocator": "pkg:npm/[email protected]"
}
]
},
{
"name": "accepts",
"SPDXID": "SPDXRef-Package-accepts",
"versionInfo": "1.3.8",
"downloadLocation": "NOASSERTION",
"licenseDeclared": "MIT",
"externalRefs": [
{
"referenceCategory": "PACKAGE-MANAGER",
"referenceType": "purl",
"referenceLocator": "pkg:npm/[email protected]"
}
]
}
],
"relationships": [
{
"spdxElementId": "SPDXRef-DOCUMENT",
"relationshipType": "DESCRIBES",
"relatedSpdxElement": "SPDXRef-Package-example-api"
},
{
"spdxElementId": "SPDXRef-Package-example-api",
"relationshipType": "DEPENDS_ON",
"relatedSpdxElement": "SPDXRef-Package-express"
},
{
"spdxElementId": "SPDXRef-Package-express",
"relationshipType": "DEPENDS_ON",
"relatedSpdxElement": "SPDXRef-Package-accepts"
}
]
}
Informasjonen er den samme, men ordnet annerledes. SPDX har en packages-liste og oppgir hver kobling
mellom elementene i relationships. licenseDeclared er det pakken sier om seg selv, og
downloadLocation kan være NOASSERTION når verktøyet ikke vet den. Se
CycloneDX vs. SPDX for hvordan de to formatene skiller seg fra hverandre utover
oppsettet.
Slik ser en svak SBOM ut
En fil kan være gyldig og likevel nesten ubrukelig. Se opp for dette:
- Ingen avhengighetsforhold. En flat liste forteller deg at en pakke er til stede, ikke hva som trakk den inn, og det er det du trenger for å rette en transitiv avhengighet.
- Ingen package URL-er. Uten en identifikator som en purl må matchingen av en komponent mot advisories baseres på gjetting ut fra navn.
-
Manglende lisenser. Mange felt som står som
NOASSERTION, betyr at SBOM-en ikke kan svare på lisensspørsmål. - Mistenkelig få komponenter. En håndfull komponenter for en stor applikasjon betyr vanligvis bare direkte avhengigheter, eller bare det én lockfile deklarerte.
- Ingenting om når eller hvordan. Uten et verktøy og en genereringskontekst kan du ikke vite hva du kan stole på at SBOM-en dekker.
- Taushet om mangler. En god SBOM sier hva den ikke kunne se. De fleste filer bare slutter, og leseren går ut fra at de er fullstendige.
Slik sjekker du din egen SBOM
- Valider formatet. Kjør den gjennom en skjemavalidator for formatet og versjonen, for et verktøy som ikke kan lese filen, kan heller ikke bruke den.
- Sjekk feltene. Sammenlign den med 2026 Minimum Elements eller listen kunden din har bedt om.
- Søk etter noe du kjenner. Velg en transitiv avhengighet, en pakke fra base-imaget ditt og et byggeverktøy, og se hvilke av dem som dukker opp.
- Sammenlign to kilder. Generer en SBOM til med en annen metode og se på forskjellen. Hver ekstra komponent i den ene filen er et spørsmål om den andre.
En SBOM fra bygget med CRACI
CRACI eksporterer de samme formatene. Forskjellen ligger i hvor innholdet kommer fra: CRACI registrerer hva hver GitHub Actions-jobb hentet, så hver komponent i SBOM-en ble faktisk trukket inn i bygget, og pakker gjenopprettet fra CI-cacher er merket som det. GitHub Actions som workflowen kjørte, vises også som komponenter, festet til commiten som ble brukt. SBOM-en til hver jobb har dessuten en fullstendighetsstatus, så manglene er oppgitt i stedet for at du må finne dem selv. Se SBOM-generering under bygget eller hvordan SBOM-verktøy står seg mot hverandre.
SBOM-eksempler: ofte stilte spørsmål
Hvordan ser en SBOM ut?
Vanligvis er den en JSON-fil, noen ganger XML. Den begynner med data om selve SBOM-en, som verktøy og tidsstempel, viser så hver komponent med navn, versjon, identifikator og lisens, og beskriver til slutt hvordan komponentene er avhengige av hverandre.
Er en SBOM en JSON-fil?
Som regel, fordi JSON er den mest brukte kodingen av både CycloneDX og SPDX. Begge formatene har også andre kodinger, og SPDX har i tillegg en tag-value-tekstform.
Hva er en purl i en SBOM?
En purl, eller package URL, er en standard identifikator for en pakke, for eksempel pkg:npm/[email protected]. Den angir økosystem, pakke og versjon i én streng, noe som lar verktøy matche komponenten pålitelig mot sårbarhetsdata.
Hvor mange komponenter bør en SBOM ha?
Det finnes ikke noe riktig antall, men den bør inkludere transitive avhengigheter, som vanligvis er langt flere enn de direkte. Svært få komponenter for en stor applikasjon betyr vanligvis at verktøyet bare så en del av den.
Kan du se en SBOM for et prosjekt med åpen kildekode?
Noen ganger. Noen prosjekter publiserer SBOM-er sammen med utgivelsene sine, og GitHub kan eksportere en fra avhengighetsgrafen til et repositorium. Den eksporten gjenspeiler det repositoriet deklarerer, ikke det et bestemt bygg brukte.
Sammenlign SBOM-en din med en registrert
Kjør én GitHub Actions-workflow på CRACI og se hvilke komponenter den nåværende SBOM-en din ikke viser.
Book en demo