金色の配線パターンが広がる基板の接写
技術解説

SBOM生成ツールはJS依存関係を半分見落とす、AIエージェントは検証0.5%の実態

目次を見る

CI/CDパイプラインにSBOM(Software Bill of Materials、ソフトウェア部品表)生成を組み込んでいる方や、AIコーディングエージェントにパッケージインストールを任せている開発チームに向けた内容です。SBOMは「ソフトウェアの事実」ではなく「ツールの出力結果」にすぎないという視点を整理します。

2026年9月にarXivへ公開された2本の論文が、同じパイプライン上の問題を両端から照らし出しました。1本はSBOM生成ツールの精度を検証したもの、もう1本はAIコーディングアシスタントがインストール前にSBOMや署名を確認する頻度を測ったものです。どちらも、現場で「やっているつもり」になりがちな工程の実態を数字で示しています。

何が起きるか

InriaとANSSI(フランスの国家情報システムセキュリティ庁)の研究チームは、3,326件のGitHubリポジトリに対して3種類のSBOM生成ツール(Syft 1.38.2、Trivy 0.68.2、cdxgen 12.0.0)を実行しました。出力は全てCycloneDX 1.6形式です。

結果は衝撃的でした。JavaScriptプロジェクトでは、ロックファイルに記載された依存パッケージのうち、Syftが検出できたのは43.78%、Trivyはさらに低く32.71%にとどまりました。Rustプロジェクトでは状況が異なり、Syftは100%、Trivyも83.85%を記録しています。

さらに厳しいのは、ロックファイルが存在しない場合の挙動です。SyftとTrivyは空のSBOMを出力しますが、論文は「オペレーターに対してエラーも警告も表示されない」と指摘しています。つまり、何も検出できていないのに、パイプラインは正常終了したように見えてしまいます。

もう1本のAIエージェントに関する研究では、Pengyin Shan氏が1,920回の試行を事前登録した形で実施しました。6つの研究用ソフトウェアプロジェクト、9種類のバリエーション(署名なし、正当なSBOM、正当な署名、正当なアテステーション、発行者偽装などの組み合わせ)、3種類のモデル、2種類のハーネスを組み合わせています。

結果、AIアシスタントがインストール前にSBOM・署名・アテステーション(証明書的な検証情報)のいずれかを開いたのは全体のわずか0.5%でした。そして1,920回中、実際にそれを検証した試行は0件です。

なぜ起きるか

原因は段階的に分解すると見えてきます。

1つ目は、ツールごとの「設計思想の違い」です。Syftはdev依存関係(開発時のみ使うパッケージ)を意図的に除外する設計ですが、これはパッケージマネージャーによって一貫していません。あるnpmプロジェクトでは、本番依存2249件を2249件正しく検出した一方、開発依存4930件は0件検出でした。ところがYarnやpnpmのプロジェクトでは、両方とも100%検出されています。同じ「除外する」という方針でも、対応するエコシステムによって結果が変わるわけです。

2つ目は「実装の不具合」です。Trivyもdev依存を除外しますが、除外処理が1階層目で止まるため、dev依存の孫依存(推移的依存関係)がルート直下の本番依存として誤って報告されるケースがありました。論文はSyftの挙動を「一貫性のない設計選択」、Trivyの挙動を「実装エラー」と明確に区別しています。

3つ目は「識別子の不一致」です。同じパッケージでも、ツールによって異なる名前やバージョンで報告されます。npmのエイリアス(別名指定)は、cdxgenとTrivyがエイリアス名で、Syftが実際のスコープ付き名で報告します。gitでピン留めされた依存関係は、コミットハッシュ・tarball URL・セマンティックバージョンという3通りの表記で出力されました。脆弱性スキャンはこの識別子を手がかりに照合するため、同じコードを2つのツールでスキャンすると異なる脆弱性リストが返ってくることになります。

4つ目は「メタデータの欠落」です。NTIA(米国電気通信情報庁)が2021年に定めたSBOM最小要素の1つであるSupplier(供給者情報)は、検証した3ツールのいずれも、JavaScript・Rustどちらのエコシステムでも埋めていませんでした。ライセンス情報もcdxgenが75.8%、Syftが60.2%に対し、Trivyは0%です。

5つ目は、AIエージェント側の問題として「検証ステップがプロンプトやワークフローに組み込まれていない」ことです。AIコーディングアシスタントは、パッケージをインストールする指示を受けたときに、SBOMや署名の確認を自発的には行いません。これは言語モデルの能力の問題というより、ツール呼び出しの手順にその工程が組み込まれていないために起きています。

自分のプロジェクトが該当するか確認する

まず、CIパイプラインで使っているSBOM生成ツールとそのバージョンを確認します。

syft version
trivy --version
cdxgen --version

次に、生成されたSBOMファイル(CycloneDXやSPDX形式)を開き、package-lock.jsonやyarn.lock、pnpm-lock.yamlに記載されているパッケージ数と突き合わせます。

# npmプロジェクトの依存関係数を確認
jq '.packages | length' package-lock.json

# 生成されたSBOM内のコンポーネント数を確認(CycloneDX形式の場合)
jq '.components | length' sbom.cyclonedx.json

数が大きくずれている場合、dev依存の扱いやロックファイルの検出に問題がある可能性があります。特にTrivyを使っている場合は、バージョンが0.68.2より古いかどうかも確認してください(0.75.0で挙動が変わっている可能性があります)。

AIコーディングエージェントを使っている場合は、エージェントにパッケージインストールを依頼する際のプロンプトやシステムプロンプトに、SBOMや署名確認のステップが明示的に書かれているかを見直してください。ほとんどの場合、何も書かれていないはずです。

対策の手順

SBOM生成側の対策として、以下を実施します。

  • ロックファイルが存在しない状態でSBOM生成が走っていないか、CIログを確認する(空のSBOMが「成功」扱いになっていないか)
  • 複数ツールを併用している場合、同じパッケージの識別子が一致するかをCIで突き合わせる検証ステップを追加する
  • SBOM生成コマンドのバージョンとフラグをバージョン管理下に置き、監査時に再現できるようにする
  • ライセンス情報やSupplier情報が必要な場合、生成ツールの出力だけに頼らず、別途メタデータソース(npm registryやCargo.ioのAPI)で補完する

AIエージェント側の対策として、パッケージインストールをエージェントに任せるワークフローでは、インストール前にSBOM・署名・アテステーションの確認を強制するステップを、MCP(Model Context Protocol、AIとツールを連携させる仕組み)経由のツール呼び出しとして明示的に組み込むことが考えられます。たとえば、インストールコマンドを直接実行させるのではなく、「このパッケージの署名を検証してから報告せよ」という中間ステップをツール定義に持たせる設計です。

また、CI上でAIエージェントがインストールを行う場合は、ネットワーク到達範囲を制限したコンテナ内で実行し、実行ログとファイルアクセスを記録する運用が、今回の研究と同じ検証手法として参考になります。

まとめ

SBOMは「ソフトウェアの事実」ではなく、「特定バージョンのツールを特定フラグで実行した結果」です。コンポーネント数の多寡だけを見て安心するのではなく、生成レシピ(ツール・バージョン・フラグ)をバージョン管理し、監査で説明できる状態にしておくことが実務上の着地点になります。

次の一歩として、まず手元のCIで使っているSBOM生成ツールのバージョンを確認し、ロックファイルとの突き合わせを一度試してみてください。AIエージェントを使った自動インストールのワークフローがあるなら、検証ステップが本当に実行されているか、ログを見返すところから始めるのが現実的です。

参考

An SBOM is a tool output, not a fact about your software

この記事について: 本記事は AI を活用して作成し、forva AI 編集部が内容を確認・監修しています。

AI 駆動開発のご相談は forva AI へ。まずはお気軽にどうぞ。