隠れた依存関係
隠れた依存関係とは、ビルドがダウンロードして使うにもかかわらず、どのロックファイルやマニフェストにも記載されないコード、パッケージ、ファイルのことで、多くのSBOMに漏れています。
最終更新日:2026年11月11日
隠れた依存関係(hidden dependency)とは、ビルドがダウンロードして使うにもかかわらず、どのロックファイルやマニフェストにも記載されないコード、パッケージ、ファイルのことです。ほとんどのSBOMツールはそうしたリストを基にしているため、隠れた依存関係はほとんどのSBOMに含まれず、最近のサプライチェーン攻撃のいくつかはまさにそこを通りました。一般的なソフトウェア工学では、モジュール間の宣言されていない結合を指すこともありますが、ここではサプライチェーンの意味で使います。
よくある隠れた依存関係
- インストールフック。 npmは、パッケージの
preinstall、install、postinstallスクリプトをnpm installの実行中に実行します(npmドキュメント)。これらのスクリプトがダウンロードしたものはpackage-lock.jsonに一切現れません。Shai-Huludワームが使ったのはこの経路です。 - ビルドスクリプト。 Cargoは、クレートをビルドする直前にその
build.rsをコンパイルして実行します(Cargo Book)。この時点でCライブラリやビルド済みバイナリをダウンロードするビルドスクリプトもあり、Cargo.lockはそれを記録しません。 - ベースイメージ。 コンテナビルドでは、ベースイメージとそのOSレイヤーはレジストリから取得され、どの言語のロックファイルにも載りません。DockerイメージのSBOMを参照してください。
- CIのステップ。 ワークフロー内のセットアップアクションや
curl | sh形式のインストーラーは、作成者が追加しない限り、ロックファイルもバージョン固定もハッシュもなしにURLから直接ツールを取得します。
リポジトリにコミットされたコード(ベンダリングされた依存関係)も、マニフェストから漏れるもう一つの経路ですが、ビルド中に取得されるものではありません。「phantom dependency」はまた別の意味で、JavaScriptで、コードが宣言せずに使っており、ホイスティングによってのみ利用できるパッケージを指します。
SBOMツールが見逃す理由
ロックファイルベースのツールはロックファイルに宣言されたリストを読むため、宣言されたものしか見えません。出力スキャナーは完成した成果物を調べて何が含まれたかを推定しますが、Rustのようなコンパイル済みコードでは推測にとどまります。どちらも、ビルドが途中で取得したものは見えません。キャッシュやビルドツールを含め、各手法が見逃すものの全体はオープンソースのSBOM生成ツールにまとめています。隠れた依存関係は、SBOM自身では明らかにできないSBOMの完全性の欠落です。
バージョン固定でも解決しません。ロックファイルが完璧でも、そこで固定したインストールフックが新しいものをダウンロードすることはあります。ビルド時に取得を行うビルドは、再現可能なビルドを実現しにくい理由のひとつでもあります。
見つけ方
- ビルドログでダウンロードを確認します。
npm installとcargo buildの出力、curlやwgetの行です。 - ロックファイルから生成したSBOMと、インストールステップが報告するパッケージを比較します。
- ベースイメージに含まれているとわかっているパッケージ(
libc6など)をSBOMで検索します。なければ、イメージのレイヤーが漏れています。 - ワークフローを
curlとwgetで検索します。
確実なのは、後から再構成するのではなく、ビルドがネットワーク経由で実際に取り込んだものを記録することです。
CRACI
CRACIは各ビルドに入ってくる通信を見ているため、ロックファイルベースのツールが見逃す隠れた依存関係を記録します。たとえばパッケージを認識するプロキシを迂回する通信をジョブが許可していたなど、すべてを把握できなかった場合は、ジョブの完全性の状態がそれを示します。さらにエグレスポリシーがビルドの到達できるホストを決めるため、ポリシーが許可しないホストへのcurl | shは失敗します。ビルド時SBOMを参照してください。