Ukryta zależność
Ukryta zależność to kod, pakiet lub plik, który build pobiera i wykorzystuje, ale którego nie wymienia żaden lockfile ani manifest, przez co większość SBOM go pomija.
Ostatnia aktualizacja: 11 listopada 2026
Ukryta zależność (hidden dependency) to kod, pakiet lub plik, który build pobiera i wykorzystuje, ale którego nie wymienia żaden lockfile ani manifest. Ponieważ większość narzędzi SBOM opiera się na tych listach, ukrytych zależności brakuje w większości SBOM, a właśnie tędy przebiegło kilka niedawnych ataków na łańcuch dostaw. W ogólnej inżynierii oprogramowania to określenie oznacza też niezadeklarowane powiązanie między modułami; tutaj chodzi o znaczenie związane z łańcuchem dostaw.
Typowe ukryte zależności
- Hooki instalacyjne. npm uruchamia skrypty
preinstall,installipostinstallpakietu podczasnpm install(dokumentacja npm). To, co pobiorą te skrypty, nigdy nie trafia dopackage-lock.json. Tą drogą poszedł robak Shai-Hulud. - Skrypty buildu. Cargo kompiluje i uruchamia
build.rscrate'a tuż przed jego zbudowaniem (Cargo Book). Niektóre skrypty buildu pobierają wtedy bibliotekę C lub gotowy plik binarny, aCargo.locktego nie odnotowuje. - Obrazy bazowe. W buildzie kontenera obraz bazowy i jego warstwy systemu operacyjnego pochodzą z rejestru, a nie z lockfile jakiegokolwiek języka. Zob. SBOM obrazów Docker.
- Kroki CI. Akcje konfiguracyjne i instalatory
curl | shw workflow pobierają narzędzia prosto z adresu URL, bez lockfile, przypiętej wersji ani skrótu, o ile autor ich nie doda.
Kod umieszczony w repozytorium (dołączone zależności) to kolejny sposób, w jaki komponenty omijają manifesty, ale nie jest on pobierany podczas buildu. „Phantom dependency” oznacza zaś coś innego: w JavaScripcie pakiet, którego kod używa bez deklarowania go, dostępny tylko dzięki hoistingowi.
Dlaczego narzędzia SBOM je pomijają
Narzędzia oparte na lockfile czytają zadeklarowaną listę w lockfile, więc widzą tylko to, co zadeklarowano. Skanery wyniku analizują gotowy artefakt i wnioskują, co do niego trafiło, co w przypadku kodu kompilowanego, takiego jak Rust, pozostaje zgadywaniem. Żadne z nich nie widzi, co build pobrał po drodze. Pełna lista tego, co pomija każde podejście, łącznie z pamięcią podręczną i narzędziami buildu, znajduje się w generatorach SBOM open source. Ukryta zależność to luka w kompletności SBOM, której sam SBOM nie jest w stanie ujawnić.
Przypinanie wersji też tego nie rozwiązuje: lockfile może być doskonały, a przypięty w nim hook instalacyjny i tak może pobrać coś nowego. Buildy, które pobierają zasoby w trakcie budowania, są też jednym z powodów, dla których odtwarzalny build trudno osiągnąć.
Jak je znaleźć
- Proszę przejrzeć log buildu pod kątem pobrań: wynik
npm installicargo buildoraz wiersze zcurllubwget. - Porównać SBOM wygenerowany z lockfile z pakietami, które zgłasza krok instalacji.
- Wyszukać w SBOM pakiet, o którym wiadomo, że jest w obrazie bazowym, np.
libc6. Jeśli go nie ma, brakuje warstw obrazu. - Przeszukać workflow pod kątem
curliwget.
Wiarygodna odpowiedź to rejestrowanie tego, co build faktycznie pobiera przez sieć, zamiast odtwarzania tego po fakcie.
CRACI
CRACI widzi ruch wchodzący do każdego buildu, więc rejestruje ukryte zależności, które pomijają narzędzia oparte na lockfile. Gdy nie mógł zobaczyć wszystkiego, np. dlatego, że zadanie dopuściło ruch omijający jego proxy rozpoznające pakiety, informuje o tym stan kompletności zadania. Jego polityka egress decyduje też, z którymi hostami build w ogóle może się połączyć, więc curl | sh do hosta niedozwolonego przez politykę kończy się niepowodzeniem. Zob. SBOM z czasu buildu.