脆弱性インテリジェンスを実用的なプロダクトにする方法:アラート一覧から修正キューへ
脆弱性インテリジェンスAPIが提供するのは、あくまでリスクの候補です。本記事では、資産、依存関係のスコープ、到達可能性、実際の攻撃での悪用状況、修正済みバージョンを組み合わせて、セキュリティアラートを対応から完了まで管理できるエンジニアリングタスクに変える方法を解説します。
依存関係リストを脆弱性インテリジェンスAPIに送信し、CVEやセキュリティアドバイザリをまとめて受け取っても、それだけで脆弱性管理プロダクトを構築したことにはなりません。開発チームが本当に必要としているのは、実際の対応につながるキューです。どのサービスが影響を受けるのか、なぜ今対応しなければならないのか、誰が修正するのか、アップグレードで何が壊れるのか、そしてリスクが解消されたことをどう証明するのか。
https://news.ycombinator.com/item?id=47094192に関するHacker Newsの議論では、アラートのノイズ、関数呼び出しの到達可能性、セキュリティ業務が開発者に押し付けられることなどが主な論点になっています。コメントが業界の総意を表すわけではありませんが、プロダクト設計者への注意喚起にはなります。スキャンのたびに赤い数字が増えるだけで、対応に必要な文脈が十分に示されなければ、ユーザーはいずれそのチャネル全体を無視するようになります。
脆弱性レコードは候補にすぎず、タスクを決めるのは資産のコンテキスト
脆弱性データベースは、パッケージの特定のバージョンが影響を受けると記述します。組織は社内で次の問いに答えなければなりません。そのバージョンは現在のビルドに実際に含まれているか、どの環境にデプロイされているか、外部から到達可能か、脆弱な関数が実行パスに含まれるか、パッチや実施可能な緩和策がすでにあるか。深刻度はあくまで判断材料の1つにすぎません。
https://google.github.io/osv.dev/api/は、パッケージのバージョンまたはコミットによるクエリに対応しており、バッチクエリやIDによる脆弱性レコードの取得にも対応しています。ソフトウェア部品表と公開脆弱性レコードを結び付けるのに適していますが、クエリ結果だけでは本番環境での露出を証明できません。ロックファイル、ビルド成果物、コンテナイメージ、稼働中のインスタンスが一致していない可能性があるため、スキャン対象を明示する必要があります。
最初のステップでは、各候補について資産の関連付けを確立します。リポジトリ、コンポーネント、解決済みバージョン、ビルド識別子、デプロイ環境、オーナーです。リポジトリのデフォルトブランチの依存関係情報しか得られない場合は、結論をそのブランチに限定し、本番システムに脆弱性があると拡大解釈しないでください。デプロイ状況を判断できない場合、タスクは資産のエビデンスを補完することであり、確実性を捏造することではありません。
複数のインテリジェンスソースを統合する前の出典情報の保持
https://google.github.io/osv.dev/data/には、対象となるエコシステムとソースデータベースが掲載されています。1つの脆弱性が複数のソースで記述されることもあり、後から訂正、撤回、影響を受けるバージョン範囲の追加が行われることもあります。プロダクトでは、エイリアスとパッケージ座標でマージしたビューを表示できますが、各ソースのID、更新日時、影響を受けるバージョン範囲、原文へのリンクは保持する必要があります。
ソースが複数あっても、信頼性が自動的に倍になるわけではありません。複数のWebサイトが同じアドバイザリを転載していることもあれば、複数のデータベースが同じ元レコードを使っていることもあります。本当に役立つクロスチェックとは、影響を受けるバージョン、修正済みバージョン、悪用の前提条件、撤回状況といった重要なフィールドを、それぞれが独立して裏付けているかを比較することです。矛盾するフィールドは、モデルに黙って1つを選ばせるのではなく、明示的に提示する必要があります。
標準化されたオブジェクトには、次の要素を含めることができます。
- 主要な脆弱性識別子、エイリアス、影響を受けるパッケージ、バージョン範囲。
- ソースレコード、初回観測日時と最終確認日時、改訂または撤回のステータス。
- 既知の修正済みバージョン、ベンダーによる緩和策、およびその適用条件。
- 組織内で照合された資産、環境、依存関係、エビデンスのタイムスタンプ。
- 優先度シグナル、人による判断、オーナー、対応ステータス。
こうしておけば、外部の記述が変わっても、上書きされた現在のレコードだけを見るのではなく、以前の判断が何に基づいていたかをチームが把握できます。
CVSSの降順ソートだけではない優先度付け
⟦GitHubのDependabotドキュメント](https://docs.github.com/en/code-security/how-tos/manage-security-alerts/manage-dependabot-alerts/view-dependabot-alerts)では、優先度の判断にCVSS、依存関係のスコープ、脆弱な関数呼び出しが検出されたかどうかといったシグナルを考慮すると説明されています。これは重要な方向性を示しています。単一のスコアを表示するだけでなく、深刻度、関連性、対応可能性を組み合わせる必要があるということです。
⟦CISA Known Exploited Vulnerabilities Catalog](https://www.cisa.gov/known-exploited-vulnerabilities-catalog)は、実際に悪用されていることが判明している脆弱性を識別するために使用され、脆弱性管理の優先度付けフレームワークの判断材料として推奨されています。KEVへの該当は重視すべきシグナルですが、それだけで組織が攻撃を受けたことが証明されるわけではなく、資産の露出評価に代わるものでもありません。
説明可能な優先度であれば、次の問いに順に答えられます。
- 資産がデプロイされているか、そして本番、社内、開発のどの環境にあるか。
- 脆弱なコンポーネントが直接依存か推移的依存か、そして最終成果物にパッケージされているか。
- 外部ユーザーや低権限ユーザーが関連するエントリポイントに到達できるか、そして脆弱なコードが実行される可能性があるか。
- 実際に確認されている悪用事例、公開されている緩和策、利用可能な修正済みバージョンの有無。
- アップグレードのコスト、互換性リスク、業務上の実施タイミングはどうか。
プロダクトでは、これらの問いを謎めいたAIリスクスコアに圧縮する必要はありません。エビデンスと不足点を表示するほうが有用なことが多くあります。たとえば「本番イメージに含まれることを確認済み」「外部への露出は未確認」「修正済みバージョンあり」「アップグレードテストは未着手」のように示せば、オーナーは次にどのエビデンスを補うべきかがひと目で分かります。
修正キューに必須のクローズ条件
多くのセキュリティダッシュボードには、Open、Dismissed、Fixedという大まかな3つのステータスしかなく、実際のエンジニアリングプロセスを表現できません。より実用的なキューには、資産確認待ち、影響確認済み、修正予定、変更検証中、緩和済み・アップグレード待ち、クローズ、不一致、リスク受容といったステータスを含めることができます。各ステータスには、そのステータスへの移行条件と、そのステータスからの移行条件が必要です。
バージョンをアップグレードしたからといって、必ずしもクローズしたことにはなりません。検証では少なくとも、新しいロックファイルやビルド成果物が影響を受けるバージョン範囲に該当しなくなったこと、関連テストが通ること、対象環境で新しい成果物が実際に稼働していることを確認する必要があります。設定による緩和策を採用した場合は、その出典、適用条件、有効期限、最終的なアップグレードの担当者を記録し、一時的な対処が恒久化しないようにします。
アラートを無視する場合にも理由が必要です。テストフィクスチャが成果物に含まれない、パッケージエコシステムの誤認識、廃止済みブランチにしか存在しない、といった点はいずれも妥当なクローズ理由になり得ますが、「今は時間がない」は同じ種類のエビデンスではありません。資産レコードも脆弱性レコードも変化し得るため、プロダクトでは再オープンできるようにしておく必要があります。
サイト内の⟦稼働中の機能とドキュメントの乖離に関する分析](https://everyinfra.com/build/live-capability-catalog)では、宣言、設定、実際のランタイムを混同してはならないことを説明しています。⟦失敗時の返金と照合のガイド](https://everyinfra.com/build/failure-refund-reconciliation)は課金を扱う記事ですが、同様に重要なイベント台帳の考え方を示しています。すべての状態変更について、その原因、入力、後続のアクションを追跡できなければなりません。
全員の受信トレイではなくオーナーの作業キューへのアラート送信
同じ脆弱性が数十のリポジトリに該当することがありますが、実際の修正は共有ベースイメージのアップグレードだけで済む場合もあれば、サービスごとに個別の検証が必要な場合もあります。通知の前にまとめましょう。共通の根本原因ごとに親タスクを作成し、影響を受ける資産ごとにサブ項目を作成します。そうしないと、重複したメッセージが見かけ上の作業量を膨らませます。
送信内容には、アセット、バージョン、環境、優先度の根拠、修正または緩和策への導線、不足しているエビデンス、明確な担当者を含めるべきです。担当者がいない場合は、エンジニアリング組織全体に一斉通知するのではなく、「未割り当て」として表示すべきです。緊急チャネルは事前に定義した条件を満たすイベントにのみ使用し、それ以外は日次キューに入れます。
再スキャンの失敗も明示的に通知すべきです。インテリジェンスソースが利用できない場合や部品表の生成が中断された場合に、緑色の「新しい脆弱性はありません」というメッセージを表示すると、危険な誤解を招きます。サイト内の⟦APIエラーと自己修復ガイド](https://everyinfra.com/build/api-errors-self-healing)を参考に、スキャン完了、部分完了、未実行はそれぞれ別の状態として扱う必要があります。
商用化ではアラート販売の拡大よりもループコストの削減に注力
初期のサービスでは、一つのエンジニアリングチームを対象に、限られた数のリポジトリとデプロイ環境を接続し、不一致の解消、アセットの帰属付け、アップグレードの検証に人が関与する形が考えられます。料金の単位は、検出した脆弱性ごとに課金するのではなく、管理対象のアセット、ワークフローの深さ、対応時の協働を軸に設計できます。アラートが増えても、顧客が得る価値が増えるわけではありません。
パイロット期間中は、候補から確定までの時間、担当者未割り当ての割合、重複タスクの統合率、修正対応に入ってからクローズまでの時間、再オープンの理由、期限切れのリスク受容項目を記録してください。「検出された脆弱性の数が減った」ことだけを示すのは避けてください。数値は、スキャンの失敗、アセットの漏れ、安易な無視によっても下がるためです。
契約更新の判断は、エンジニアリング上の成果に立ち返るべきです。担当者がより早くリスクを理解できるようになったか、重複した調査が減ったか、修正に検証可能なエビデンスが残るか、カバレッジの中断を適時に検知できるか、といった点です。本記事は脆弱性インテリジェンスのプロダクト化の手法を論じるものであり、EveryInfraが脆弱性管理サービスを提供することを示唆するものではなく、特定のシステムに対するセキュリティ上の結論を示すものでもありません。
脆弱性データは公開情報のレイヤーであり、プロダクトの本当の価値は組織の内側で生まれます。外部の記録を実際のアセットと結び付け、リスクを実行可能なタスクとして説明し、ビルド、デプロイ、ランタイムのエビデンスを用いてクローズすることです。これがなければ、どれほど網羅的な脆弱性ライブラリでも、ToDoリストが長くなるだけです。
参考資料 BL-15