CyberFix Note
セキュアコーディング

依存ライブラリ管理とSCA。SBOMで攻撃面を把握する

対象の目安: Webアプリ開発者・DevOps/プラットフォーム担当 / 実務レベル

ソウ攻撃・脆弱性リサーチ担当
・ 約17分で読めます
依存ライブラリ管理とSCA。SBOMで攻撃面を把握する

現代のアプリケーションは、自分たちが書いたコードよりも、外部から取り込んだライブラリのほうが行数も依存関係も多いのが普通です。npmやpip、Maven、Goのモジュールを少しインストールしただけで、その先にある間接的な依存(依存先がさらに依存しているもの)まで含めると、数百から数千のパッケージが自分のアプリの一部として動いています。この「自分で書いていないのに自分の責任になるコード」をどう把握し、どう守るかが、サプライチェーンセキュリティの出発点です。

ここで鍵になるのが、SBOM(Software Bill of Materials、ソフトウェア部品表)とSCA(Software Composition Analysis、ソフトウェア構成分析)という二つの考え方です。SBOMは「自分のアプリが何でできているか」を機械可読な台帳として書き出すこと、SCAは「その部品の中に既知の脆弱性を持つものがないか」を脆弱性データベースと突き合わせて見つけることです。台帳がなければ突き合わせる対象が分からず、突き合わせがなければ台帳はただのリストで終わります。両者は車の両輪です。

この記事では、SBOMの代表的な2つの標準であるSPDXとCycloneDXの違い、SCAがどんな原理で脆弱性を見つけ何を見落とすのか、DependabotやRenovateによる依存更新の自動化、そしてこれらをCI/CDにどう組み込み、どこで「ビルドを止める/止めない」を線引きするかという実務の判断基準まで、原理から噛み砕いて整理します。Log4Shellのような事件がなぜあれほど広範囲に及んだのかを思い出しながら読むと、SBOMの価値が腹落ちするはずです。

まず全体像を、SBOMとSCAおよび更新自動化が「何を担い、何を入力に、何を出力するか」という観点で一覧にします。

要素役割主な入力主な出力代表的な実装例
SBOM生成構成部品の台帳化ロックファイル・ビルド成果物・コンテナイメージSPDX/CycloneDX形式のファイルSyft, cdxgen, 各言語のSBOMプラグイン
SCA(脆弱性突合)既知脆弱性の検出SBOMまたは依存情報脆弱性レポート(CVE/GHSA一覧)OWASP Dependency-Check, Trivy, Grype, osv-scanner
更新自動化脆弱な版の置き換え依存マニフェスト・脆弱性アラート更新プルリクエストDependabot, Renovate
脆弱性DB突合の参照元CVE・各エコシステムの勧告パッケージ/版と脆弱性の対応NVD, GitHub Advisory(GHSA), OSV.dev

この4つが連携して初めて、「何を使っているか把握し(SBOM)、その中の危険を見つけ(SCA)、安全な版へ置き換える(更新自動化)」という一連の流れが回ります。以下、それぞれを掘り下げます。

なぜSBOMが必要なのか。Log4Shellが示した「把握できていない」リスク

SBOMの価値が最もはっきり分かったのが、2021年末のLog4Shell(Apache Log4jの脆弱性、CVE-2021-44228)でした。多くの組織がまず直面したのは「自社の製品やシステムのどこでLog4jを使っているのか分からない」という問題でした。直接依存していなくても、別のライブラリやミドルウェアが内部でLog4jを使っているケースが多く、影響範囲の特定そのものに何日もかかった組織が少なくありません。詳しくは

でも触れています。

ここで効くのがSBOMです。各システムについて「使っている部品の一覧」を機械可読な形で保管しておけば、新しい脆弱性が公表された瞬間に「log4j-coreのこのバージョンを含む成果物はどれか」を一覧で検索できます。人手で各プロジェクトのビルド設定を開いて回る作業が、台帳への問い合わせ一回に置き換わるわけです。これは攻撃を防ぐ仕組みというより、事故が起きたときの初動を速くする仕組みだと理解すると正確です。

SBOMの典型的な記載項目は、コンポーネント名、バージョン、サプライヤー、一意な識別子(後述のPURLなど)、ライセンス、ハッシュ値、依存関係などです。重要なのは、これらが「人が読むためのドキュメント」ではなく「機械が処理するためのデータ」である点です。だからこそ標準フォーマットが定められています。

注意

SBOMは作って終わりではありません。ビルドのたびに依存は変わるため、リリースごとに自動生成し、成果物と一緒に保管する運用にしないと、いざというとき「古い台帳しかない」状態になります。SBOMは生鮮品だと考え、CI/CDで毎回作り直すのが基本です。

SBOMの2大標準。SPDXとCycloneDXの違い

SBOMのフォーマットは事実上、SPDXとCycloneDXの2つが標準として広く使われています。どちらが優れているという話ではなく、出自と得意分野が違います。

SPDXはLinux Foundationが主導するプロジェクトで、もともとオープンソースのライセンスやコンプライアンス管理を起点に発展しました(略称の正式名称は2.x系までのSoftware Package Data Exchangeから、3.0系でSystem Package Data Exchangeへと再定義されています)。SPDXはISO/IEC 5962:2021として国際標準にもなっています(このISO標準はSPDX 2.2.1がベース)。その後、モデルを大きく刷新したSPDX 3.0が2024年4月に公開され、執筆時点では3.0.1が最新の安定版です。3.0ではSecurity Profileが整備され、脆弱性やVEX関連の情報も扱えるようになりました。ライセンス情報の詳細な記述に強く、法務・コンプライアンス観点での部品表として根強い支持があります。

CycloneDX はOWASPコミュニティ発のプロジェクトで、こちらはセキュリティを起点に設計されています。国際標準としてはECMA-424として標準化されており、SBOMだけでなくVEX(Vulnerability Exploitability eXchange、脆弱性が実際に悪用可能かを伝える形式)や、SaaSBOM・CBOM(暗号部品表)・AI/ML-BOMといった派生にも対応します。脆弱性との連携を最初から想定しているため、SCAや攻撃面の把握という文脈ではCycloneDXを選ぶ現場が多い傾向です。

観点SPDXCycloneDX
主導Linux FoundationOWASP
標準化ISO/IEC 5962:2021(2.2.1ベース)、3.0系が最新ECMA-424
起点・得意ライセンス/コンプライアンスセキュリティ/脆弱性連携
VEX対応3.0のSecurity Profileで対応ネイティブに対応
よく使う場面OSSライセンス監査、調達要件SCA、脆弱性管理、攻撃面把握

実務上の選び方はシンプルです。ライセンスコンプライアンスや顧客・規制からの提出要件が主目的ならSPDX、社内のセキュリティ運用(脆弱性検出やVEX運用)が主目的ならCycloneDX、という分け方で問題ありません。両方を生成できるツールも多いので、迷うなら片方に固定せず両形式で出力しておく手もあります。

なお、フォーマットをまたいで部品を一意に識別する仕組みとしてPURL(Package URL)がよく使われます。pkg:npm/lodash@4.17.21 のように「エコシステム/パッケージ名/バージョン」を一意な文字列で表すもので、SBOMとSCAをつなぐ共通言語として機能します。

「SPDXとCycloneDX、どちらを採用すべきか」で議論が止まる現場をよく見ます。ですが本質はフォーマット選びではなく、SBOMを毎ビルド自動生成して保管し、脆弱性が出たときに検索できる運用を持っているかどうかです。形式は後から変換もできます。まず一本、自動生成のパイプラインを通すことを優先してください。

編集部

SCAの原理。何を見つけ、何を見落とすのか

SCA(ソフトウェア構成分析)は、依存ライブラリの一覧やSBOMを脆弱性データベースと突き合わせ、「既知の脆弱性を持つ版を使っていないか」を検出します。ここで大事なのは、SCAが見つけるのは原則として「公表済みの既知の脆弱性」だという点です。未知の脆弱性(ゼロデイ)や、あなたの自作コードのバグは対象外です。SCAは

で扱うSAST/DASTとは役割が異なり、互いに補完する関係にあります。

突合の参照元となる脆弱性データベースには、主に次のものがあります。

  • NVD(National Vulnerability Database)。NISTが運営する米国政府の脆弱性カタログで、CVEに紐づく情報の中心。CPE(製品識別子)でのマッチングが特徴。
  • GitHub Advisory Database(GHSA)。npm・PyPI・Maven・RubyGems・NuGet・Go・Composer・Rust などエコシステム単位で整理された勧告。
  • OSV.dev。GoogleとOpenSSFが関わる分散型データベースで、OSVスキーマにより「どのパッケージのどのバージョン範囲が影響を受けるか」を機械可読・高精度で表現する。

検出方式には大きく2系統あります。ひとつはNVDのCPEに基づくマッチングで、OWASP Dependency-Checkが代表例です。これはライブラリから推定したCPE識別子をCVEに突き合わせるため、エコシステム固有DBが拾わないものまで拾える一方、推定がゆるい分、誤検知(実際には該当しないのに警告が出る)が増えやすい傾向があります。もうひとつは、ロックファイルのパッケージ名とバージョンをエコシステム固有の勧告(GHSAやOSV)に直接突き合わせる方式で、Trivy・Grype・osv-scannerなどが採用します。こちらは精度が高く誤検知が少ない反面、DBが対応していないエコシステムや、CVEはあるが勧告化されていないものを取りこぼすことがあります。

ツール主な検出方式得意領域注意点
OWASP Dependency-CheckNVD/CPEマッチングJava/.NET等、広く拾う誤検知が比較的多い
Trivyエコシステム勧告+αコンテナ・IaC・依存を横断設定次第で出力が多くなる
Grypeエコシステム勧告(GHSA/OSV等)依存・コンテナの精度重視対応エコシステム依存
osv-scannerOSVスキーマ突合ロックファイル・SBOM入力OSV未収録分は取りこぼし

ここから導かれる実務的な教訓は、「1つのツールだけに頼らない」ことと、「検出結果を鵜呑みにせず誤検知を前提に運用する」ことです。誤検知は無視するのではなく、なぜ該当しないのかを記録(VEXや抑制設定)に残すことで、次回以降のノイズを減らせます。

OWASP Dependency-CheckはNVDのデータフィードとCPEに基づいて既知脆弱性を検出する旗艦プロジェクトで、Maven/Gradle/Jenkins/GitHub Actions等に統合できます。

依存更新の自動化。DependabotとRenovate

脆弱性を見つけても、安全な版に置き換えなければ攻撃面は減りません。しかし依存の更新は手間がかかり、後回しにされがちです。これを「プルリクエスト(PR)が勝手に上がってくる」状態にして、レビューとマージだけに集中できるようにするのが更新自動化ツールです。

GitHubに統合されているDependabotは、用途の異なる2つの機能を持ちます。ひとつはバージョン更新(version updates)で、dependabot.yml という設定ファイルを置くと、脆弱性の有無にかかわらず依存を定期的に最新へ追従するPRを作ります。もうひとつはセキュリティ更新(security updates)で、Dependabotアラートが検出した脆弱な依存について、依存グラフを壊さずに直せる最小限のパッチ版へ更新するPRを自動で作成し、アラートに紐づけます。設定では更新頻度(daily/weekly等)、対象エコシステム、無視するパッケージ、メジャー/マイナー/パッチの粒度などを制御できます。

Renovate(Mendが提供するオープンソースツール)はDependabotより設定の自由度が高く、複数の更新をまとめる(グルーピング)、自動マージの条件を細かく決める、対応するパッケージマネージャが幅広いといった特徴があります。GitHub以外のプラットフォームでも使いやすいのが利点です。どちらを選ぶかは、GitHub中心で手軽に始めたいならDependabot、細かな運用ポリシーを作り込みたいならRenovate、という整理でおおむね合います。

# .github/dependabot.yml の最小例
# npmの依存を毎週チェックし、更新PRを自動で作成する
version: 2
updates:
  - package-ecosystem: "npm"
    directory: "/"
    schedule:
      interval: "weekly"
    open-pull-requests-limit: 10

注意

自動更新で見落としがちなのが、PRが増えすぎて誰もレビューしなくなる「PR疲れ」と、テストが不十分な状態での自動マージです。更新が壊れていないかを担保するのは結局テストです。CIのテストが薄いまま自動マージを有効にすると、安全のための仕組みが新しい不具合の入口になります。自動化の前にテストの整備を、という順序を崩さないでください。

CIへの組み込みと「止める/止めない」の判断基準

SBOM生成・SCA・更新自動化は、CI/CDに組み込んで初めて継続的に効きます。組み込みの基本形は次の通りです。

  1. ビルド時にSBOMを自動生成し、成果物と一緒に保管する。
  2. そのSBOM(または依存情報)に対してSCAを実行し、脆弱性レポートを出す。
  3. Dependabot/Renovateで更新PRを継続的に上げ、マージで攻撃面を減らす。

ここで現場が必ず迷うのが、「脆弱性が見つかったらビルドを失敗させるべきか」です。結論から言うと、最初から全件で失敗させるのは避けるべきです。導入直後は既存の依存に大量の指摘が出るのが普通で、いきなり全部を失敗扱いにすると開発が止まり、現場は「とりあえずスキップ」を覚えてしまいます。これではせっかくの仕組みが形骸化します。

現実的な進め方は、重大度と「修正版があるか(fix available)」を軸にしたしきい値の段階的な引き上げです。たとえば最初は「Critical かつ修正版あり」だけをビルド失敗の条件にし、それ以外は警告として記録に残します。運用が回り始めたらHighまで広げる、というように厳格化を後追いさせます。重大度の評価にはCVSSが使われますが、スコアだけで機械的に判断せず、実際に悪用可能か(攻撃経路に乗っているか)を加味するのが望ましく、ここでVEXが役立ちます。CVSSの読み方は

もあわせてどうぞ。

「脆弱性ゼロ」を目標に掲げると、達成不能な理想に現場が疲弊します。目指すべきは脆弱性ゼロではなく、『重大なものを、許容できる時間内に、確実に直し切れる流れ』を持っていることです。SBOMとSCAは、その流れを支える可視化と検出の土台だと位置づけると、運用が長続きします。

編集部

このテーマはサプライチェーン攻撃全体の一部でもあります。依存ライブラリそのものが乗っ取られる、いわゆる悪意ある更新や typosquatting などの手口は

で詳しく扱っています。SBOM/SCAは「既知の脆弱性」には強い一方、攻撃者が意図的に仕込んだ悪意あるコードの検出は別の対策(パッケージの署名検証、ピン留め、公開元の確認など)が必要になる点も押さえておいてください。

よくある質問

SBOMとSCAは何が違うのですか。
SBOMは『自分のアプリが何でできているか』を機械可読な台帳として書き出すこと、SCAはその台帳や依存情報を脆弱性データベースと突き合わせて『既知の危険な部品』を見つけることです。台帳作りと突き合わせという、役割の異なる工程です。
SPDXとCycloneDX、どちらを選べばよいですか。
ライセンスやコンプライアンスの提出要件が主目的ならSPDX、社内のセキュリティ運用や脆弱性・VEX連携が主目的ならCycloneDXが向きます。両形式を出力できるツールも多いので、迷うなら両方生成しておく手もあります。
SCAを入れれば脆弱性は防げますか。
SCAが見つけるのは原則として公表済みの既知脆弱性です。未知の脆弱性や自作コードのバグ、意図的に仕込まれた悪意あるコードは別の対策が必要です。SCAは万能ではなく、SAST/DASTや署名検証などと組み合わせて使います。
検出された脆弱性が誤検知のようです。どう扱えばよいですか。
無視するのではなく、なぜ該当しないのかをVEXや抑制設定として記録に残します。これにより次回以降の同じ警告を抑えられ、本当に対応すべきものに集中できます。判断に迷う場合は最新の公式情報や社内の専門家・法務に確認してください。
いきなりCIでビルドを失敗させても大丈夫ですか。
おすすめしません。導入直後は既存依存に大量の指摘が出るため、最初は『Critical かつ修正版あり』など狭い条件だけ失敗にし、運用が回ってから段階的に厳格化するのが現実的です。

まとめ

依存ライブラリ管理は「何を使っているかを台帳化(SBOM)し、その中の危険を見つけ(SCA)、安全な版へ置き換える(更新自動化)」という流れを、CI/CDで継続的に回すことに尽きます。検出だけで満足せず、直し切る流れまで作って初めて攻撃面が減ります。なお脆弱性対応の手順や重大度の判断は状況により変わるため、実際の対応にあたっては各ツール・データベースの最新の公式情報、および自社の法務・セキュリティ専門家に確認したうえで進めてください。

依存管理とSCA導入チェックリスト

  • ビルドのたびにSBOMを自動生成し、成果物と一緒に保管しているか
  • SBOMの形式(SPDX/CycloneDX)を目的に合わせて選んでいるか、両形式を出力しているか
  • SCAを少なくとも1つCIに組み込み、脆弱性レポートを出しているか
  • DependabotまたはRenovateで更新PRが継続的に上がる状態になっているか
  • 自動マージの前提となるテストが十分に整備されているか
  • ビルド失敗のしきい値を重大度と修正版有無で段階的に設計しているか
  • 誤検知をVEXや抑制設定として記録し、ノイズを減らす運用があるか
  • 新しい脆弱性公表時にSBOMから影響範囲を即座に検索できる状態か

出典・参考

この記事をシェア

関連する記事