123% flere rapporterede CVE'er pr. dag i 2026 end sidste år.

SBOM

En SBOM bør beskrive det build, der blev leveret

En SBOM fra buildet registreres, mens buildet kører, ud fra den trafik, der faktisk kom ind i det. De fleste SBOM-generatorer rekonstruerer i stedet listen bagefter ud fra lockfilen eller outputtet, og det overser de skjulte afhængigheder, et build selv henter. Her kan du se hvorfor, og hvad registrering af buildet ændrer.

Opdateret

What a scanner reads versus what the build pulled in A scanner reads the lockfile, which lists direct packages A, B and C and transitive packages D and E, so its SBOM contains only those. CRACI sees the network traffic into the build job, so its recorded SBOM also contains the hidden dependencies no lockfile lists: code downloaded by an install hook, a download by a build script, and the base image layers. A scanner reads the lockfile package-lock.json direct A B C transitive D E Scanned SBOM A, B, C, D, E only what the lockfile lists CRACI sees the traffic into the build A B C D E install hook download build script download base image layers build job on CRACI Recorded SBOM every package it fetched, hidden too Dashed: hidden dependencies, listed in no lockfile

Build-SBOM, kilde-SBOM, analyseret SBOM

CISA's vejledning om SBOM-typer sorterer SBOM'er efter, hvornår og hvordan de laves. Tre af dem dækker næsten alle SBOM-generatorer i brug:

Type Sådan laves den Hvad den kan overse
Kilde Ud fra kildefiler, manifester og lockfiles, som regel med et SCA-værktøj Runtime-, plugin- eller platformkomponenter; alt, der ikke er deklareret i filerne
Build Som en del af det build, der skaber det frigivelsesklare artefakt Det, build-miljøet ikke kan se, og derfor bør fuldstændigheden angives
Analyseret Efter buildet, ved at analysere en eksekverbar fil, en pakke eller et container-image Komponenter, værktøjet ikke kan genkende; resultaterne afhænger af heuristik

CISA nævner to fordele ved en build-SBOM: større tillid til, at SBOM'en repræsenterer artefaktet korrekt, på grund af de oplysninger, der er tilgængelige under build- og CI/CD-processen, og større troværdighed, fordi det samme build-workflow kan signere både SBOM'en og artefaktet. Den nævnte ulempe er, at du måske skal ændre build-processen for at generere en. Med CRACI er den ændring én linje, runs-on: craci, og registreringen følger med runneren.

At scanne en mappe eller at registrere et build

De fleste SBOM-generatorer er scannere. Du retter en mod et kildetræ eller et container-image, og den udleder, hvad den tror, der gik ind, ved at læse manifester, lockfiles, installerede pakker eller binærfiler. Det er nyttigt, og for software, du ikke selv har bygget, er det ofte den eneste mulighed.

Svagheden er, at en scanner kun ser det, den har foran sig. Hvis der ikke er committet en lockfile, hvis afhængighederne ikke blev installeret før scanningen, eller hvis produktet leveres som en kompileret binærfil, har scanneren mindre at arbejde med, end buildet havde. En scanning, der slet ikke finder nogen komponenter, producerer stadig et gyldigt SBOM-dokument, og det er den del, der snyder folk.

CRACI gør det anderledes. Det genererer SBOM'en inde i sin egen CI-runner, så det leverede artefakt er det beskrevne artefakt. Det er ikke en scanning, der kørte et sted i nærheden.

SBOM basics: SPDX, CycloneDX and OpenVEX

Hvad en SBOM registrerer, hvordan formaterne SPDX og CycloneDX adskiller sig i praksis, og hvad OpenVEX tilføjer om, hvorvidt en sårbarhed faktisk påvirker et produkt.

Petteri Pulkkinen og Erika Marttinen ved Kubernetes Community Days Helsinki 2026, 16:50 til 22:05 af SBOMbastic: Getting Ready for Upcoming EU Cybersecurity Regulation in Software Supply Chains.

Hvad en scanning afhænger af

Syft, Trivy, cdxgen, Microsoft SBOM Tool, GitHubs eksport af afhængighedsgrafen og Socket CLI udleder alle en SBOM ud fra det, de kan læse. Mønstrene nedenfor følger af, hvordan disse værktøjer ifølge deres dokumentation virker.

Værktøjer er uenige om, hvad der tæller som en komponent

Hver generator afgør selv, hvad der tæller som en komponent, og hvilke filer den stoler på, så det samme fastlåste commit giver dem hver sin liste.

Noget af det handler om navne. Værktøjer identificerer den samme GitHub Action under forskellige package URL-typer, så de kan angive det samme og alligevel ikke matche. Det er også en del af problemet: En SBOM, der bruger en anden identifikator for en komponent, er sværere at matche mod sårbarhedsdata.

Om du installerede først, kan betyde mere end værktøjet

Express 5.2.1 committer ikke en lockfile. På en ren checkout har en generator, der resolver afhængigheder ud fra lockfiles eller et installeret træ, ingen af delene foran sig, så ingen af de npm-afhængigheder, der er deklareret i package.json, når dokumentet. Den kan stadig returnere en liste, lavet af det, den ellers genkender, for eksempel GitHub Actions og de workflow-filer, der henviser til dem. Intet værktøj her er i stykker.

På en installeret kopi af det samme repository ændrer ét Syft-flag svaret igen. Samme værktøj, samme træ, samme version. En Syft-scanning af en mappe rapporterer bevidst, hvad et projekt deklarerer, og den cataloger, der læser installerede pakker, er ikke med i standardsættet for mapper.

Noget software har intet manifest at læse

Repositoriet anthropics/claude-code ved v2.1.259 har intet afhængighedsmanifest af nogen art: ingen package.json, lockfile eller tilsvarende. Det, hver generator returnerer for det, er sat sammen af andre filtyper, så svaret siger mere om værktøjet end om projektet.

Den udgivne npm-pakke er ikke meget anderledes. @anthropic-ai/claude-code deklarerer nul runtime-afhængigheder og otte platformspecifikke pakker, der pakker en færdigbygget binærfil ind. @openai/codex 0.149.1 har samme form. Det, der kører på udviklerens maskine, er en kompileret binærfil, som ingen manifestlæser kan se ind i. Det er ikke en fejl i et enkelt værktøj. Det er en distributionsmodel, som scanning bagefter ikke kan beskrive.

Versioner og leverandører

Hvor to værktøjer finder den samme pakke, er de ikke altid enige om versionen. Ét kan fastlåse en GitHub Action på en commit-SHA, mens et andet rapporterer et release-tag. Et sårbarhedsopslag på den forkerte version giver et selvsikkert forkert svar.

Leverandørfeltet, et af NTIA's minimumselementer, er ofte tomt, fordi de fleste generatorer ikke har nogen kilde til det.

Skjulte afhængigheder: det, ingen scanning kan se

Alle værktøjerne ovenfor starter fra lockfilen eller fra buildets output og udleder, hvad der gik ind. Et build henter mere end det. Disse skjulte afhængigheder står ikke i nogen lockfile, så en scanning kan ikke finde dem:

  • Install-hooks. npm-scripts som preinstall og postinstall kører under installationen og kan downloade mere kode. Det er sådan, Shai-Hulud-ormen kørte.
  • Build-scripts. Blandt andre downloader Rust-build-scripts det, de har brug for, under buildet.
  • Base-images. Et container-build henter et base-image og dets styresystemlag, som ingen sprogspecifik lockfile angiver.
  • Caches og build-værktøjer. Pakker gendannet fra CI-caches og værktøjer installeret af setup-trin kommer også ind uden om lockfilen.

At scanne outputtet bagefter lukker ikke hullet. En færdig binærfil, især kompileret kode som Rust, lader scanneren gætte på, hvad der gik ind i den.

To builds, to SBOM'er

Der er endnu en grund til, at en scanning ikke kan træde i stedet for buildet: De fleste builds er ikke reproducerbare. Byg det samme commit to gange lige efter hinanden, og der er ingen garanti for, at du får de samme pakker. Pakkehåndteringer resolver og installerer i den rækkefølge, svarene ankommer, og det betyder mest, når der ikke er nogen lockfile, som i mange Python-projekter, og build-trin kan indeholde deres egen tilfældighed. Reproducerbare builds, byte for byte, er mulige med værktøjer som Nix, men de er sjældne.

Så en SBOM genereret senere, på en anden maskine eller fra et andet build, beskriver et build, der måske aldrig blev leveret. Kun den SBOM, der er registreret under det CI-build, der producerede en release, beviser, hvad der er i produktion.

Hvad registrering af buildet ændrer

CRACI ser trafikken; det gør scannere ikke. Det kører dine GitHub Actions-jobs på sine egne runnere og ser netværkstrafikken ind i hvert build, så SBOM'en angiver, hvad jobbet faktisk hentede, inklusive transitive og skjulte afhængigheder, og ikke hvad et manifest siger, det burde have brug for.

Det er ved caches, at registrering under buildet bliver svær. En pakke gendannet fra en cache rører aldrig et pakkeregistry, så en proxy alene ville overse den. CRACI sender dokumentationen for afhængighederne med cachen, så pakker gendannet fra en cache bliver i SBOM'en for det job, der gendannede dem. Se hvad GitHub Actions-cachen skjuler.

Registrerede økosystemer omfatter npm, PyPI, RubyGems, Cargo, Go, Nix, OCI, apt, apk og Git-kilder samt download-presets til Yocto og OpenEmbedded. JFrog Artifactory-spejle til npm og PyPI virker. Deklarerede licensmetadata følger med i eksporten. SBOM'er eksporteres i CycloneDX og SPDX. Siden om SBOM-generering gennemgår den fulde funktionalitet.

At se trafikken virker også den anden vej. Et build har brug for pakker fra kendte kilder og udgiver sit output til kendte steder. CRACI's egress-politik tillader kun dem og blokerer straks enhver anden udgående forbindelse, så malware, der forsøger at sende dine secrets til en angribers server, fejler. Fordi politikken tillader det, buildet har brug for, i stedet for at lede efter kendte ondsindede hosts, holder den, selv hvis du er det første mål for et angreb, ingen har set før, som med Shai-Hulud. Se sådan stopper en egress-politik eksfiltrering.

Container- og Docker-SBOM'er

Det er ved container-images, at forskellen viser sig mest. De gængse måder at få en Docker-SBOM på analyserer alle imaget: Syft og Trivy scanner det, docker scout sbom indekserer indholdet, når imaget ikke har nogen SBOM-attestation, og BuildKits SBOM-attestation, der slås til med --sbom=true, kører som standard en Syft-baseret scanner over den sidste image-stage. Det ældre plugin docker sbom er udfaset til fordel for docker scout sbom.

Hver af dem læser det færdige image, så de ser det, der stadig kan genkendes i lagene. De ser ikke, hvad buildet hentede undervejs. CRACI registrerer det job, der bygger imaget: De images og pakker, jobbet henter fra OCI-registries og pakkekilder, kommer ind i den samme SBOM som resten af buildet. For et image, du ikke selv har bygget, er scanning stadig den praktiske løsning. Se hvad SBOM'er for Docker-images overser.

Fuldstændighed, angivet pr. job

En registreret SBOM er kun så god som registreringen. I stedet for at præsentere hver SBOM som komplet angiver CRACI fuldstændigheden for hvert job og hver cache i en af fem statusser:

  • Complete. CRACI observerede fuldstændig dokumentation for jobbet, og hver gendannet cache var komplet.
  • Complete with connections. Kravene blev opfyldt, men jobbet brugte en eller flere brugerdefinerede netværksforbindelser, så det er værd at gennemgå, hvad der kom ind gennem dem.
  • Incomplete. CRACI identificerede et forhold, der kan efterlade afhængigheder uden for SBOM'en.
  • Unavailable. CRACI kunne ikke færdiggøre evalueringen af dokumentationen.
  • Not recorded. Jobbet er ældre end rapporteringen af fuldstændighed.

Fuldstændighed er transitiv på tværs af caches. Hvis et job gendanner en ufuldstændig cache, er dets SBOM også ufuldstændig, og enhver cache, det job producerer, fører den ufuldstændige status videre. Du ved, hvilke SBOM'er du kan stole på, og hvilke der skal kigges nærmere på.

The hard parts: hooks, noise and staying current

Tre problemer, som foredraget peger på: post-install-hooks, der henter ting, som intet manifest oplister, at finde de afhængigheder, der betyder noget, i en lang liste, og at holde SBOM'en opdateret, hvilket betyder at generere den i CI ved hvert build.

Petteri Pulkkinen og Erika Marttinen ved Kubernetes Community Days Helsinki 2026, 25:39 til 27:22 af SBOMbastic: Getting Ready for Upcoming EU Cybersecurity Regulation in Software Supply Chains.

Provenance via API'et

SBOM'en er én del af det, CRACI registrerer for hvert job. API'et returnerer SBOM'er, netværkstraces og provenance, alt sammen registreret fra det samme build.

Hvor en scanner stadig er det rigtige værktøj

Registrering under buildet dækker software, du bygger. For et tredjeparts-image eller en binærfil, du ikke selv har bygget, er en scanner stadig det praktiske valg, og værktøjerne ovenfor er gode og meget brugte. Pointen er ikke, at scannere er dårlige. Det er, at SBOM'en for dine egne releases bør komme fra det build, der lavede dem.

En CRACI-SBOM har også sine egne begrænsninger. Den dækker jobs, der kører på CRACI-runnere, hvilket i dag betyder GitHub Actions på Linux, med andre CI-systemer på roadmappen.

Skal du vælge mellem værktøjer? Se SBOM-værktøjer sammenlignet, eller se, hvordan SBOM'er fra buildet passer ind i arbejdet med CRA-overholdelse. Syft, Trivy og cdxgen side om side finder du i hvad open source-generatorer af SBOM'er overser.

SBOM'er fra buildet: ofte stillede spørgsmål

Hvad er en SBOM fra buildet?

En SBOM fra buildet, som CISA kalder en build-SBOM, genereres som en del af buildet af det frigivelsesklare artefakt. I stedet for at rekonstruere komponentlisten ud fra filer bagefter beskriver den, hvad buildet selv brugte. CRACI registrerer den ud fra de pakker, hvert GitHub Actions-job faktisk hentede.

Hvad er forskellen på en build-SBOM og en analyseret SBOM?

En analyseret SBOM genereres efter buildet ved at analysere et artefakt som en eksekverbar fil eller et container-image, hvilket generelt kræver heuristik. En build-SBOM genereres under buildet ud fra de oplysninger, buildet har. Analyserede SBOM'er virker uden adgang til buildet, og det gør dem til det rigtige valg for software, du ikke selv har bygget.

Hvordan genererer jeg en SBOM for et Docker-image?

For et eksisterende image scanner du det med en generator som Syft, Trivy eller docker scout sbom. BuildKit kan også vedhæfte en SBOM-attestation, når du bygger, ved at scanne det endelige image. For at registrere, hvad buildet af et image trak ind, kører du buildet på en CRACI-runner: Jobbets SBOM dækker de images og pakker, det hentede.

Hvad er skjulte afhængigheder?

Alt, hvad et build henter, og som ingen lockfile angiver: kode downloadet af npm-install-hooks, filer, som Rust-build-scripts downloader under buildet, og base-imaget og dets styresystemlag i et container-build. Værktøjer, der læser lockfilen eller scanner outputtet, overser dem. CRACI registrerer dem, fordi det ser trafikken ind i buildet.

Hvorfor giver to builds af den samme kode forskellige SBOM'er?

Fordi de fleste builds ikke er reproducerbare. Pakkehåndteringen resolver og installerer pakker i den rækkefølge, svarene ankommer, især uden en lockfile, og build-trin kan indeholde tilfældighed. Byg det samme commit to gange lige efter hinanden, og det andet build kan indeholde andre pakker. Kun den SBOM, der er registreret under det build, der producerede en release, beviser, hvad den release indeholder.

Er en SBOM fra buildet altid komplet?

Ikke automatisk. En registrering er kun så god som det, den kan observere, så CRACI angiver fuldstændigheden for hvert job og hver cache: Complete, Complete with connections, Incomplete, Unavailable eller Not recorded. Du ved, hvilke SBOM'er du kan stole på, og hvilke der skal kigges nærmere på.

Erstatter en SBOM fra buildet SBOM-scannere?

For den software, du bygger, ja: SBOM'en for dine releases bør komme fra de builds, der lavede dem. For tredjeparts-images og binærfiler, du ikke selv har bygget, er en scanner stadig det praktiske valg. SBOM-værktøjer sammenlignet gennemgår mulighederne.

Hvilken SBOM-generator bruger CRACI?

Ingen. CRACI scanner ikke filer. En pakkebevidst proxy på dets runnere registrerer de pakker, hvert job henter fra npm, PyPI, RubyGems, Cargo, Go, Nix, OCI, apt, apk og Git-kilder samt download-presets til Yocto og OpenEmbedded, og eksporterer resultatet i CycloneDX eller SPDX.

Sammenlign en SBOM fra dit eget build

Book en demo, og kør et af dine workflows på CRACI. Sæt dets SBOM ved siden af den, dit nuværende værktøj producerer, og se, hvor de adskiller sig.

Book en demo