SBOM
SBOM powinien opisywać build, który dostarczono
SBOM z czasu buildu jest rejestrowany podczas działania buildu, na podstawie ruchu, który faktycznie do niego wszedł. Większość generatorów SBOM odtwarza natomiast listę później z lockfile lub wyniku buildu, co pomija ukryte zależności pobierane przez sam build. Oto dlaczego i co zmienia rejestrowanie buildu.
Zaktualizowano
Build SBOM, source SBOM, analyzed SBOM
Wytyczne CISA dotyczące typów SBOM dzielą SBOM-y według tego, kiedy i jak powstają. Trzy z nich obejmują niemal każdy używany generator SBOM:
| Typ | Jak powstaje | Co może pominąć |
|---|---|---|
| Source | Z plików źródłowych, manifestów i lockfile, zwykle przez narzędzie SCA | Komponenty środowiska uruchomieniowego, wtyczek lub platformy; wszystko, czego nie zadeklarowano w plikach |
| Build | Jako część buildu tworzącego artefakt do wydania | Wszystko, czego środowisko buildu nie widzi, dlatego należy określać kompletność |
| Analyzed | Po buildzie, przez analizę pliku wykonywalnego, pakietu lub obrazu kontenera | Komponenty, których narzędzie nie potrafi rozpoznać; wyniki zależą od heurystyk |
CISA wymienia dwie zalety build SBOM: większą pewność, że SBOM prawidłowo przedstawia artefakt, dzięki informacjom
dostępnym podczas procesu buildu i CI/CD, oraz większe zaufanie, ponieważ ten sam workflow buildu może podpisać zarówno
SBOM, jak i artefakt. Jako wadę podaje to, że do jego wygenerowania może być konieczna zmiana procesu buildu. W CRACI ta zmiana to jeden
wiersz, runs-on: craci, a rejestrowanie przychodzi razem z runnerem.
Skanowanie folderu a rejestrowanie buildu
Większość generatorów SBOM to skanery. Wskazuje się im drzewo źródłowe lub obraz kontenera, a one ustalają, co ich zdaniem do niego trafiło, odczytując manifesty, lockfile, zainstalowane pakiety lub pliki binarne. To przydatne, a w przypadku oprogramowania, którego nie budują Państwo sami, często jedyna możliwość.
Słabość polega na tym, że skaner widzi tylko to, co ma przed sobą. Jeśli lockfile nie trafił do repozytorium, jeśli zależności nie zainstalowano przed skanem lub jeśli produkt jest dostarczany jako skompilowany plik binarny, skaner ma mniej materiału niż build. Skan, który nie znalazł żadnych komponentów, nadal daje poprawny dokument SBOM i właśnie to często zaskakuje.
CRACI działa inaczej. Generuje SBOM wewnątrz własnego runnera CI, więc dostarczony artefakt jest artefaktem opisanym. Nie jest to skan uruchomiony gdzieś obok.
SBOM basics: SPDX, CycloneDX and OpenVEX
Co zapisuje SBOM, czym w praktyce różnią się formaty SPDX i CycloneDX oraz co OpenVEX wnosi do pytania, czy podatność rzeczywiście dotyczy produktu.
Petteri Pulkkinen i Erika Marttinen na Kubernetes Community Days Helsinki 2026, od 16:50 do 22:05 nagrania SBOMbastic: Getting Ready for Upcoming EU Cybersecurity Regulation in Software Supply Chains.
Od czego zależy skan
Syft, Trivy, cdxgen, Microsoft SBOM Tool, eksport grafu zależności GitHub i Socket CLI ustalają SBOM na podstawie tego, co potrafią odczytać. Poniższe wzorce wynikają ze sposobu działania tych narzędzi opisanego w ich dokumentacji.
Narzędzia nie zgadzają się co do tego, co jest komponentem
Każdy generator sam decyduje, co jest komponentem i którym plikom ufać, więc ten sam przypięty commit daje każdemu z nich inną listę.
Częściowo chodzi o nazewnictwo. Narzędzia identyfikują tę samą GitHub Action pod różnymi typami package URL, więc mogą wymieniać to samo, a mimo to się nie zgadzać. To też część problemu: SBOM używający innego identyfikatora komponentu trudniej dopasować do danych o podatnościach.
Wcześniejsza instalacja może znaczyć więcej niż wybór narzędzia
Express 5.2.1 nie ma lockfile w repozytorium. Na czystym checkoucie generator rozwiązujący zależności z lockfile lub
zainstalowanego drzewa nie ma przed sobą ani jednego, ani drugiego, więc żadna z zależności npm zadeklarowanych w
package.json nie trafia do dokumentu. Nadal może zwrócić listę złożoną z tego, co jeszcze rozpozna, na
przykład GitHub Actions i odwołujących się do nich plików workflow. Żadne z tych narzędzi nie jest zepsute.
Na zainstalowanej kopii tego samego repozytorium jedna flaga Syft znów zmienia odpowiedź. To samo narzędzie, to samo drzewo, ta sama wersja. Skan katalogu w Syft z założenia zgłasza to, co deklaruje projekt, a kataloger odczytujący zainstalowane pakiety nie należy do domyślnego zestawu dla katalogów.
Niektóre oprogramowanie nie ma manifestu do odczytania
Repozytorium anthropics/claude-code w wersji v2.1.259 nie ma żadnego manifestu zależności: ani
package.json, ani lockfile, ani odpowiednika. To, co zwraca każdy generator, jest składane z innych typów
plików, więc odpowiedź mówi więcej o narzędziu niż o projekcie.
Opublikowany pakiet npm niewiele się różni. @anthropic-ai/claude-code deklaruje zero zależności uruchomieniowych i osiem pakietów specyficznych dla platformy,
które opakowują gotowy plik binarny. @openai/codex 0.149.1 ma taką samą strukturę. Na maszynie programisty działa
skompilowany plik binarny, do którego nie zajrzy żaden czytnik manifestów. To nie wada konkretnego narzędzia. To model
dystrybucji, którego skanowanie po fakcie nie potrafi opisać.
Wersje i dostawcy
Gdy dwa narzędzia znajdują ten sam pakiet, nie zawsze zgadzają się co do jego wersji. Jedno może przypinać GitHub Action do SHA commita, a drugie podawać tag wydania. Wyszukiwanie podatności po złej wersji daje błędną odpowiedź, która brzmi pewnie.
Pole dostawcy, jeden z minimalnych elementów NTIA, często pozostaje puste, ponieważ większość generatorów nie ma dla niego źródła.
Ukryte zależności: czego nie zobaczy żaden skan
Każde z powyższych narzędzi zaczyna od lockfile lub wyniku buildu i ustala, co do niego trafiło. Build pobiera jednak więcej. Tych ukrytych zależności nie wymienia żaden lockfile, więc skan nie może ich znaleźć:
-
Hooki instalacyjne. Skrypty npm
preinstallipostinstalldziałają podczas instalacji i mogą pobierać dodatkowy kod. W ten sposób działał robak Shai-Hulud. - Skrypty buildu. Między innymi skrypty buildu w Rust pobierają to, czego potrzebują, w czasie buildu.
- Obrazy bazowe. Build kontenera pobiera obraz bazowy i jego warstwy systemu operacyjnego, których nie wymienia żaden lockfile języka.
- Cache i narzędzia buildu. Pakiety przywrócone z cache CI i narzędzia instalowane przez kroki konfiguracyjne również trafiają do buildu poza lockfile.
Późniejsze skanowanie wyniku nie zamyka tej luki. Gotowy plik binarny, zwłaszcza kod kompilowany, taki jak Rust, zmusza skaner do zgadywania, co do niego trafiło.
Dwa buildy, dwa SBOM-y
Jest drugi powód, dla którego skan nie może zastąpić buildu: większość buildów nie jest odtwarzalna. Jeśli zbudować ten sam commit dwa razy z rzędu, nie ma gwarancji, że otrzyma się te same pakiety. Menedżery pakietów rozwiązują i instalują pakiety w kolejności nadchodzenia odpowiedzi, co ma największe znaczenie, gdy nie ma lockfile, jak w wielu projektach Python, a kroki buildu mogą zawierać własną losowość. Buildy odtwarzalne co do bajta są możliwe, z narzędziami takimi jak Nix, ale rzadkie.
Dlatego SBOM wygenerowany później, na innej maszynie lub z innego buildu, opisuje build, który mógł nigdy nie zostać dostarczony. Tylko SBOM zarejestrowany podczas buildu CI, który wytworzył wydanie, dowodzi, co jest na produkcji.
Co zmienia rejestrowanie buildu
CRACI widzi ruch; skanery nie. Uruchamia Państwa zadania GitHub Actions na własnych runnerach i widzi ruch sieciowy wchodzący do każdego buildu, więc SBOM wymienia to, co zadanie faktycznie pobrało, łącznie z zależnościami przechodnimi i ukrytymi, a nie to, czego według manifestu powinno potrzebować.
To na cache rejestrowanie w czasie buildu staje się trudne. Pakiet przywrócony z cache nigdy nie łączy się z rejestrem pakietów, więc samo proxy by go pominęło. CRACI przenosi dowody zależności razem z cache, dzięki czemu pakiety przywrócone z cache pozostają w SBOM zadania, które je przywróciło. Zob. co ukrywa cache GitHub Actions.
Wykrywane ekosystemy to między innymi npm, PyPI, RubyGems, Cargo, Go, Nix, OCI, apt, apk i źródła Git, a także presety pobierania Yocto i OpenEmbedded. Działają mirrory npm i PyPI w JFrog Artifactory. Eksport zawiera metadane deklarowanych licencji. SBOM-y eksportuje się w CycloneDX i SPDX. Pełne możliwości opisuje strona generowanie SBOM.
Widoczność ruchu działa też w drugą stronę. Build potrzebuje pakietów ze znanych źródeł i publikuje wynik w znanych miejscach. Polityka ruchu wychodzącego CRACI zezwala tylko na nie i natychmiast blokuje każde inne połączenie wychodzące, więc złośliwe oprogramowanie próbujące wysłać Państwa sekrety na serwer napastnika ponosi porażkę. Ponieważ polityka zezwala na to, czego potrzebuje build, zamiast szukać znanych złych hostów, działa nawet wtedy, gdy są Państwo pierwszym celem ataku, którego nikt wcześniej nie widział, jak w przypadku Shai-Hulud. Zob. jak polityka ruchu wychodzącego zatrzymuje eksfiltrację.
SBOM-y kontenerów i Dockera
Obrazy kontenerów to miejsce, w którym różnica jest najbardziej widoczna. Wszystkie typowe sposoby uzyskania Docker SBOM
analizują obraz: Syft i Trivy go skanują, docker scout sbom indeksuje jego zawartość, gdy obraz nie ma
poświadczenia SBOM, a poświadczenie SBOM w BuildKit, włączane przez --sbom=true, domyślnie uruchamia skaner
oparty na Syft na końcowym etapie obrazu. Starsza wtyczka docker sbom jest wycofana na rzecz
docker scout sbom.
Każde z tych narzędzi odczytuje gotowy obraz, więc widzi to, co nadal da się rozpoznać w warstwach. Nie widzi tego, co build pobrał po drodze. CRACI rejestruje zadanie budujące obraz: obrazy i pakiety pobierane przez zadanie z rejestrów OCI i źródeł pakietów trafiają do tego samego SBOM co reszta buildu. W przypadku obrazu, którego nie zbudowali Państwo sami, praktycznym wyborem nadal jest skanowanie. Zob. czego brakuje w SBOM-ach obrazów Docker.
Kompletność określana dla każdego zadania
Zarejestrowany SBOM jest tak dobry jak sama rejestracja. Zamiast przedstawiać każdy SBOM jako kompletny, CRACI określa kompletność dla każdego zadania i każdego cache, w jednym z pięciu stanów:
- Complete. CRACI zaobserwował kompletne dowody zadania, a każdy przywrócony cache był kompletny.
- Complete with connections. Wymagania zostały spełnione, ale zadanie korzystało z co najmniej jednego niestandardowego połączenia sieciowego, więc warto przejrzeć, co przez nie przeszło.
- Incomplete. CRACI wykrył warunek, który mógł spowodować pominięcie zależności w SBOM.
- Unavailable. CRACI nie mógł dokończyć oceny dowodów.
- Not recorded. Zadanie powstało przed wprowadzeniem raportowania kompletności.
Kompletność przenosi się przez cache. Jeśli zadanie przywraca niekompletny cache, jego SBOM też jest niekompletny, a każdy cache wytworzony przez to zadanie przenosi ten status dalej. Wiedzą Państwo, na których SBOM-ach można polegać, a które wymagają ponownej weryfikacji.
The hard parts: hooks, noise and staying current
Trzy problemy wskazane w wystąpieniu: hooki post-install pobierające rzeczy, których nie wymienia żaden manifest, znalezienie istotnych zależności na długiej liście oraz utrzymanie aktualnego SBOM-u, co oznacza generowanie go w CI przy każdym buildzie.
Petteri Pulkkinen i Erika Marttinen na Kubernetes Community Days Helsinki 2026, od 25:39 do 27:22 nagrania SBOMbastic: Getting Ready for Upcoming EU Cybersecurity Regulation in Software Supply Chains.
Pochodzenie przez API
SBOM to jedna z rzeczy, które CRACI rejestruje dla każdego zadania. API zwraca SBOM-y, ślady sieciowe i dane o pochodzeniu, wszystkie zarejestrowane z tego samego buildu.
Gdzie skaner nadal jest właściwym narzędziem
Rejestrowanie w czasie buildu obejmuje oprogramowanie, które Państwo budują. W przypadku obrazu lub pliku binarnego firm trzecich, którego Państwo nie zbudowali, praktycznym wyborem nadal jest skaner, a opisane wyżej narzędzia są sprawne i szeroko stosowane. Nie chodzi o to, że skanery są złe. Chodzi o to, że SBOM Państwa własnych wydań powinien pochodzić z buildu, który je wytworzył.
SBOM z CRACI również ma ograniczenia. Obejmuje zadania uruchamiane na runnerach CRACI, co dziś oznacza GitHub Actions na Linuksie, a inne systemy CI są w planach rozwoju.
Wybierają Państwo narzędzia? Zob. porównanie narzędzi SBOM lub to, jak SBOM-y z czasu buildu wpisują się w pracę nad zgodnością z CRA. Porównanie Syft, Trivy i cdxgen opisuje strona czego nie widzą generatory SBOM open source.
SBOM-y z czasu buildu: najczęściej zadawane pytania
Czym jest SBOM z czasu buildu?
SBOM z czasu buildu, który CISA nazywa build SBOM, powstaje w ramach budowania artefaktu do wydania. Zamiast odtwarzać listę komponentów z plików później, opisuje to, czego użył sam build. CRACI rejestruje go na podstawie pakietów faktycznie pobranych przez każde zadanie GitHub Actions.
Czym build SBOM różni się od analyzed SBOM?
Analyzed SBOM powstaje po buildzie przez analizę artefaktu, takiego jak plik wykonywalny lub obraz kontenera, co zwykle wymaga heurystyk. Build SBOM powstaje podczas buildu, z informacji, którymi build dysponuje. Analyzed SBOM działa bez dostępu do buildu, dlatego jest właściwym wyborem dla oprogramowania, którego nie budują Państwo sami.
Jak wygenerować SBOM obrazu Docker?
Istniejący obraz należy zeskanować generatorem, takim jak Syft, Trivy lub docker scout sbom. BuildKit może też dołączyć poświadczenie SBOM podczas budowania, skanując obraz końcowy. Aby zarejestrować to, co pobrał build obrazu, należy uruchomić build na runnerze CRACI: SBOM zadania obejmuje pobrane obrazy i pakiety.
Czym są ukryte zależności?
To wszystko, co build pobiera, a czego nie wymienia żaden lockfile: kod pobierany przez hooki instalacyjne npm, pliki pobierane przez skrypty buildu w Rust w czasie buildu oraz obraz bazowy i jego warstwy systemu operacyjnego w buildzie kontenera. Narzędzia odczytujące lockfile lub skanujące wynik je pomijają. CRACI je rejestruje, ponieważ widzi ruch wchodzący do buildu.
Dlaczego dwa buildy tego samego kodu dają różne SBOM-y?
Ponieważ większość buildów nie jest odtwarzalna. Menedżer pakietów rozwiązuje i instaluje pakiety w kolejności nadchodzenia odpowiedzi, zwłaszcza bez lockfile, a kroki buildu mogą zawierać losowość. Jeśli zbudować ten sam commit dwa razy z rzędu, drugi build może zawierać inne pakiety. Tylko SBOM zarejestrowany podczas buildu, który wytworzył wydanie, dowodzi, co to wydanie zawiera.
Czy SBOM z czasu buildu jest zawsze kompletny?
Nie automatycznie. Rejestracja jest tak dobra jak to, co może zaobserwować, dlatego CRACI określa kompletność dla każdego zadania i każdego cache: Complete, Complete with connections, Incomplete, Unavailable lub Not recorded. Wiedzą Państwo, na których SBOM-ach można polegać, a które wymagają ponownej weryfikacji.
Czy SBOM z czasu buildu zastępuje skanery SBOM?
W przypadku oprogramowania, które Państwo budują, tak: SBOM Państwa wydań powinien pochodzić z buildów, które je wytworzyły. Dla obrazów i plików binarnych firm trzecich, których Państwo nie zbudowali, praktycznym wyborem nadal jest skaner. Opcje przedstawia porównanie narzędzi SBOM.
Jakiego generatora SBOM używa CRACI?
Żadnego. CRACI nie skanuje plików. Proxy rozpoznające pakiety na jego runnerach rejestruje pakiety pobierane przez każde zadanie z npm, PyPI, RubyGems, Cargo, Go, Nix, OCI, apt, apk i źródeł Git, a także z presetów pobierania Yocto i OpenEmbedded, i eksportuje wynik w CycloneDX lub SPDX.
SBOM z Państwa własnego buildu do porównania
Proszę umówić demo i uruchomić jeden ze swoich workflow na CRACI. Proszę zestawić jego SBOM z tym, który tworzy Państwa obecne narzędzie, i zobaczyć różnice.
Umów demo