SBOM
En SBOM ska beskriva bygget som levererades
En SBOM från bygget registreras medan bygget körs, utifrån trafiken som faktiskt kom in i det. De flesta SBOM-generatorer rekonstruerar i stället listan i efterhand från lockfilen eller resultatet, vilket missar de dolda beroenden som ett bygge hämtar på egen hand. Här är varför, och vad en registrering av bygget ändrar.
Uppdaterad
Bygg-SBOM, käll-SBOM och analyserad SBOM
CISA:s vägledning om SBOM-typer sorterar SBOM:er efter när och hur de tas fram. Tre av dem täcker nästan varje SBOM-generator som används:
| Typ | Hur den tas fram | Vad den kan missa |
|---|---|---|
| Källa | Från källfiler, manifest och lockfiler, oftast med ett SCA-verktyg | Komponenter för körtid, plugins eller plattform; allt som inte deklareras i filerna |
| Bygge | Som en del av bygget som skapar den släppbara artefakten | Det som byggmiljön inte kan se, vilket är skälet till att fullständigheten bör anges |
| Analyserad | Efter bygget, genom analys av en körbar fil, ett paket eller en containeravbild | Komponenter som verktyget inte känner igen; resultaten beror på heuristik |
CISA anger två fördelar med en bygg-SBOM: större tillförsikt om att SBOM:en återger artefakten korrekt, tack vare
informationen som finns tillgänglig under bygget och CI/CD-processen, och större tillit, eftersom samma byggarbetsflöde
kan signera både SBOM:en och artefakten. Nackdelen som CISA anger är att du kan behöva ändra byggprocessen för att
generera en. Med CRACI är den ändringen en rad, runs-on: craci, och registreringen följer med
runnern.
Att skanna en mapp eller att registrera ett bygge
De flesta SBOM-generatorer är skannrar. Du pekar en mot ett källträd eller en containeravbild, och den räknar ut vad den tror ingick genom att läsa manifest, lockfiler, installerade paket eller binärer. Det är användbart, och för programvara du inte själv har byggt är det ofta det enda alternativet.
Svagheten är att en skanner bara ser det som finns framför den. Om ingen lockfile checkades in, om beroenden inte installerades före skanningen eller om produkten levereras som en kompilerad binär har skannern mindre att arbeta med än bygget hade. En skanning som inte hittar några komponenter alls ger ändå ett giltigt SBOM-dokument, vilket är det som överraskar många.
CRACI gör på ett annat sätt. Den genererar SBOM:en i sin egen CI-runner, så att artefakten som levereras är artefakten som beskrivs. Det är ingen skanning som kördes någonstans i närheten.
SBOM basics: SPDX, CycloneDX and OpenVEX
Vad en SBOM registrerar, hur formaten SPDX och CycloneDX skiljer sig åt i praktiken och vad OpenVEX tillför om huruvida en sårbarhet faktiskt påverkar en produkt.
Petteri Pulkkinen och Erika Marttinen på Kubernetes Community Days Helsinki 2026, 16:50 till 22:05 av SBOMbastic: Getting Ready for Upcoming EU Cybersecurity Regulation in Software Supply Chains.
Vad en skanning är beroende av
Syft, Trivy, cdxgen, Microsoft SBOM Tool, exporten av GitHubs beroendegraf och Socket CLI räknar alla ut en SBOM från det de kan läsa. Mönstren nedan följer av hur de här verktygen enligt sin dokumentation fungerar.
Verktygen är oense om vad som räknas som en komponent
Varje generator avgör själv vad som räknas som en komponent och vilka filer den ska lita på, så samma låsta commit ger var och en av dem en annan lista.
En del av det handlar om namngivning. Verktyg identifierar samma GitHub Action under olika typer av package URL, så de kan lista samma sak och ändå inte matcha. Det är också en del av problemet: en SBOM som använder en annan identifierare för en komponent är svårare att matcha mot sårbarhetsdata.
Om du installerade först kan spela större roll än verktyget
Express 5.2.1 checkar inte in någon lockfile. Pekad mot en ren utcheckning har en
generator som löser beroenden från lockfiler eller ett installerat träd
varken det ena eller det andra framför sig, så inga av npm-beroendena som deklareras i
package.json når dokumentet. Den kan ändå returnera en lista,
sammansatt av annat den känner igen, till exempel GitHub Actions och
arbetsflödesfilerna som hänvisar till dem. Inget verktyg här är trasigt.
På en installerad kopia av samma repo ändrar en enda Syft-flagga svaret igen. Samma verktyg, samma träd, samma version. Enligt sin utformning rapporterar en katalogskanning med Syft vad ett projekt deklarerar, och katalogiseraren som läser installerade paket ingår inte i standarduppsättningen för kataloger.
Viss programvara har inget manifest att läsa
Repot anthropics/claude-code vid v2.1.259 har inget
beroendemanifest av något slag: ingen package.json, lockfile eller
motsvarande. Det varje generator returnerar för det sätts ihop av andra
filtyper, så svaret säger mer om verktyget än om projektet.
Det publicerade npm-paketet är inte mycket annorlunda. @anthropic-ai/claude-code deklarerar noll körtidsberoenden och
åtta plattformsspecifika paket som omsluter en förbyggd binär.
@openai/codex 0.149.1 har samma form. Det som körs på
utvecklarens dator är en kompilerad binär som ingen manifestläsare kan se
in i. Det är inte en brist i något enskilt verktyg. Det är en distributionsmodell som
skanning i efterhand inte kan beskriva.
Versioner och leverantörer
När två verktyg hittar samma paket är de inte alltid överens om dess version. Ett kan låsa en GitHub Action till en commit-SHA medan ett annat rapporterar en release-tagg. En sårbarhetsuppslagning som bygger på fel version ger ett självsäkert felaktigt svar.
Leverantörsfältet, ett av NTIA:s minimielement, blir ofta tomt, eftersom de flesta generatorer inte har någon källa för det.
Dolda beroenden: det ingen skanning kan se
Varje verktyg ovan utgår från lockfilen eller byggets resultat och räknar ut vad som ingick. Ett bygge hämtar mer än så. De här dolda beroendena listas inte i någon lockfile, så en skanning kan inte hitta dem:
-
Installationshookar. npm-skripten
preinstallochpostinstallkörs under installationen och kan ladda ner mer kod. Det var så Shai-Hulud-masken kördes. - Byggskript. Byggskript i bland annat Rust laddar ner det de behöver under bygget.
- Basavbilder. Ett containerbygge hämtar en basavbild och dess operativsystemslager, som ingen språkspecifik lockfile listar.
- Cachar och byggverktyg. Paket som återställs från CI-cachar och verktyg som installeras av setup-steg kommer också in utanför lockfilen.
Att skanna resultatet i efterhand täpper inte till luckan. En färdig binär, särskilt kompilerad kod som Rust, tvingar skannern att gissa vad som ingick.
Två byggen, två SBOM:er
Det finns ett andra skäl till att en skanning inte kan ersätta bygget: de flesta byggen är inte reproducerbara. Bygg samma commit två gånger i rad, och det finns ingen garanti för att du får samma paket. Pakethanterare löser och installerar i den ordning svaren kommer, vilket spelar störst roll när det inte finns någon lockfile, som i många Python-projekt, och byggsteg kan innehålla egen slumpmässighet. Byte för byte reproducerbara byggen är möjliga, med verktyg som Nix, men de är ovanliga.
En SBOM som genereras senare, på en annan maskin eller från ett annat bygge, beskriver alltså ett bygge som kanske aldrig levererades. Bara SBOM:en som registrerades under CI-bygget som producerade en release bevisar vad som finns i produktion.
Vad en registrering av bygget ändrar
CRACI ser trafiken; det gör inte skannrar. Den kör dina GitHub Actions-jobb på sina egna runners och ser nätverkstrafiken som kommer in i varje bygge, så SBOM:en listar vad jobbet faktiskt drog in, inklusive transitiva och dolda beroenden, snarare än vad ett manifest säger att det borde behöva.
Cachar är där registrering under bygget blir svår. Ett paket som återställs från en cache rör aldrig ett paketregister, så en proxy ensam skulle missa det. CRACI låter bevisen om beroenden följa med cachen, så paket som återställs från en cache stannar i SBOM:en för jobbet som återställde dem. Se vad GitHub Actions-cachen döljer.
Ekosystem som upptäcks omfattar npm, PyPI, RubyGems, Cargo, Go, Nix, OCI, apt, apk och Git-källor, plus förinställningar för nedladdning i Yocto och OpenEmbedded. Speglar av npm och PyPI i JFrog Artifactory fungerar. Deklarerad licensmetadata ingår i exporten. SBOM:er exporteras i CycloneDX och SPDX. Sidan SBOM-generering tar upp hela funktionen.
Att se trafiken fungerar också åt andra hållet. Ett bygge behöver paket från kända källor och publicerar sitt resultat till kända platser. CRACI:s egress-policy tillåter bara dem och blockerar varje annan utgående anslutning omedelbart, så skadlig kod som försöker skicka dina hemligheter till en angripares server misslyckas. Eftersom policyn tillåter det bygget behöver i stället för att leta efter kända skadliga värdar håller den även om du är det första målet för en attack som ingen har sett tidigare, som med Shai-Hulud. Se så stoppar en egress-policy exfiltrering.
SBOM:er för containrar och Docker
Det är i containeravbilder som skillnaden syns mest. De vanliga sätten att få en Docker-SBOM analyserar alla avbilden:
Syft och Trivy skannar den, docker scout sbom indexerar dess innehåll när avbilden saknar SBOM-attestering,
och BuildKits SBOM-attestering, som slås på med --sbom=true, kör som standard en Syft-baserad skanner
över avbildens sista steg. Det äldre pluginet docker sbom är utfasat till förmån för
docker scout sbom.
Alla dessa läser den färdiga avbilden, så de ser det som fortfarande går att känna igen i lagren. De ser inte vad bygget hämtade längs vägen. CRACI registrerar jobbet som bygger avbilden: avbilderna och paketen som jobbet hämtar från OCI-register och paketkällor hamnar i samma SBOM som resten av bygget. För en avbild du inte har byggt är en skanning fortfarande det praktiska alternativet. Se vad SBOM:er för Docker-avbilder missar.
Fullständighet, angiven per jobb
En registrerad SBOM är bara så bra som registreringen. I stället för att presentera varje SBOM som komplett anger CRACI fullständigheten för varje jobb och varje cache, i en av fem statusar:
- Complete. CRACI observerade fullständiga bevis för jobbet, och varje återställd cache var komplett.
- Complete with connections. Kraven uppfylldes, men jobbet använde en eller flera anpassade nätverksanslutningar, så det är värt att granska vad som kom in genom dem.
- Incomplete. CRACI identifierade ett förhållande som kan göra att beroenden saknas i SBOM:en.
- Unavailable. CRACI kunde inte slutföra utvärderingen av bevisen.
- Not recorded. Jobbet är äldre än fullständighetsrapporteringen.
Fullständighet är transitiv över cachar. Om ett jobb återställer en ofullständig cache är även dess SBOM ofullständig, och varje cache som jobbet producerar för statusen ofullständig vidare. Du vet vilka SBOM:er du kan lita på och vilka som behöver en andra granskning.
The hard parts: hooks, noise and staying current
Tre problem som föredraget lyfter fram: post-install-hooks som hämtar sådant som inget manifest listar, att hitta de beroenden som spelar roll i en lång lista och att hålla SBOM:en aktuell, vilket innebär att generera den i CI vid varje bygge.
Petteri Pulkkinen och Erika Marttinen på Kubernetes Community Days Helsinki 2026, 25:39 till 27:22 av SBOMbastic: Getting Ready for Upcoming EU Cybersecurity Regulation in Software Supply Chains.
Proveniens via API:t
SBOM:en är en del av det CRACI registrerar för varje jobb. API:t returnerar SBOM:er, nätverksspårningar och proveniens, allt registrerat från samma bygge.
Där en skanner fortfarande är rätt verktyg
Registrering under bygget täcker programvara du bygger. För en tredjepartsavbild eller binär som du inte har byggt är en skanner fortfarande det praktiska valet, och verktygen ovan är kapabla och allmänt använda. Poängen är inte att skannrar är dåliga. Den är att SBOM:en för dina egna releaser ska komma från bygget som skapade dem.
En SBOM från CRACI har också sina egna begränsningar. Den täcker jobb som körs på CRACI-runners, vilket i dag betyder GitHub Actions på Linux, med andra CI-system på roadmapen.
Väljer du mellan verktyg? Se SBOM-verktyg i jämförelse, eller se hur SBOM:er från bygget passar in i arbetet med CRA-efterlevnad. För Syft, Trivy och cdxgen sida vid sida, se vad SBOM-generatorer med öppen källkod missar.
SBOM:er från bygget: vanliga frågor
Vad är en SBOM från bygget?
En SBOM från bygget, som CISA kallar en build SBOM, genereras som en del av bygget av den släppbara artefakten. I stället för att rekonstruera komponentlistan från filer i efterhand beskriver den vad bygget självt använde. CRACI registrerar den utifrån paketen som varje GitHub Actions-jobb faktiskt hämtade.
Vad är skillnaden mellan en bygg-SBOM och en analyserad SBOM?
En analyserad SBOM genereras efter bygget genom analys av en artefakt, till exempel en körbar fil eller en containeravbild, vilket i allmänhet kräver heuristik. En bygg-SBOM genereras under bygget, utifrån information som bygget har. Analyserade SBOM:er fungerar utan åtkomst till bygget, vilket gör dem till rätt val för programvara du inte har byggt.
Hur genererar jag en SBOM för en Docker-avbild?
För en befintlig avbild skannar du den med en generator som Syft, Trivy eller docker scout sbom. BuildKit kan också koppla en SBOM-attestering när du bygger, genom att skanna den slutliga avbilden. För att registrera vad bygget av en avbild drog in kör du bygget på en CRACI-runner: jobbets SBOM täcker avbilderna och paketen det hämtade.
Vad är dolda beroenden?
Allt som ett bygge hämtar och som ingen lockfile listar: kod som laddas ner av installationshookar i npm, filer som byggskript i Rust laddar ner under bygget och basavbilden och dess operativsystemslager i ett containerbygge. Verktyg som läser lockfilen eller skannar resultatet missar dem. CRACI registrerar dem eftersom den ser trafiken som kommer in i bygget.
Varför ger två byggen av samma kod olika SBOM:er?
Därför att de flesta byggen inte är reproducerbara. Pakethanteraren löser och installerar paket i den ordning svaren kommer, särskilt utan lockfile, och byggsteg kan innehålla slumpmässighet. Bygg samma commit två gånger i rad, och det andra bygget kan innehålla andra paket. Bara SBOM:en som registrerades under bygget som producerade en release bevisar vad den releasen innehåller.
Är en SBOM från bygget alltid komplett?
Inte automatiskt. En registrering är bara så bra som det den kan observera, så CRACI anger fullständigheten för varje jobb och varje cache: Complete, Complete with connections, Incomplete, Unavailable eller Not recorded. Du vet vilka SBOM:er du kan lita på och vilka som behöver en andra granskning.
Ersätter en SBOM från bygget SBOM-skannrar?
För programvaran du bygger, ja: SBOM:en för dina releaser ska komma från byggena som skapade dem. För tredjepartsavbilder och binärer som du inte har byggt är en skanner fortfarande det praktiska valet. SBOM-verktyg i jämförelse går igenom alternativen.
Vilken SBOM-generator använder CRACI?
Ingen. CRACI skannar inte filer. En paketmedveten proxy på dess runners registrerar paketen som varje jobb hämtar från npm, PyPI, RubyGems, Cargo, Go, Nix, OCI, apt, apk och Git-källor, plus förinställningar för nedladdning i Yocto och OpenEmbedded, och exporterar resultatet i CycloneDX eller SPDX.
Jämför en SBOM från ditt eget bygge
Boka en demo och kör ett av dina arbetsflöden på CRACI. Ställ dess SBOM bredvid den ditt nuvarande verktyg producerar och se var de skiljer sig.
Boka en demo