脆弱性
脆弱性管理のノイズを減らす方法
ノイズとは、注意を奪うのに、やるべきことを何も変えない検出結果です。発生源で、次の順に減らします。正確なインベントリ、重複排除、依存関係の削減、悪用可能性のコンテキスト、そしてポリシーに基づく担当者への振り分け。そのうえで、残ったものを順位付けします。各ステップが次のステップを安くするため、順番が重要です。優先順位付けツールはノイズを取り除くのではなく、ノイズに順位を付けるだけです。
更新日
脆弱性のノイズはどこから来るのか
あるバックログを、検出結果の発生源ごとに分類してみます。以下の数値は説明用でありベンチマークではありませんが、分類そのものは、チームが自社のバックログをサンプリングしたときに実際に見つかるものです。
| 検出結果の発生源 | 1,000件の検出結果のうち(説明用) | それを取り除くステップ |
|---|---|---|
| 出荷しないコンポーネント:ロックファイルやマニフェストの記載、ビルダーレイヤー、開発・テスト用ツール | 300 | 1. インベントリを正す |
| 複数のツールから、またはリポジトリごとに報告される同じCVE | 250 | 2. 各検出結果を一度だけ数える |
| 誤った一致:CPE名の衝突、ディストリビューションのバックポート | 80 | 1. インベントリを正す |
| 自社製品では悪用できない正しい検出結果 | 150 | 4. 悪用可能性のコンテキストを加える |
| まだ修正がない正しい検出結果 | 70 | 5. 有効期限付きのポリシー判断 |
| 担当者のいない検出結果 | 50 | 5. 担当者に振り分ける |
| 順位付けして修正するもの | 100 | 優先順位付け |
1つの区別を押さえておくと、このページの残りが理解しやすくなります。これらの検出結果の一部は誤検知です。コンポーネントが存在しない、またはそのバージョンが影響を受けないため、検出結果そのものが誤っています。その他はノイズです。検出結果は正しいものの、今週やるべきことを変えません。両者には別々の対処が必要で、混同すると、正しい検出結果を抑制したり、誤った検出結果について議論したりすることになります。
| 誤検知:検出結果が誤っている | ノイズ:正しいが緊急ではない |
|---|---|
| コンポーネントが出荷物に含まれていない | 自社製品では脆弱なコードに到達できない、またはトリガーできない |
| 一致が誤っている:CPEの衝突、またはバージョン番号からは見えないバックポートされた修正 | まだ修正が存在しない、または製品が社内向けで外部に公開されていない |
| インベントリと照合を正して対処する | コンテキスト、記録された判断、担当者で対処する |
ステップ1. インベントリを出荷物と一致させる
後続のすべてのステップがインベントリの誤りを増幅するため、これが最大の手段です。記載されているのに出荷されないコンポーネントは、すべてのスキャナー、すべてのリポジトリ、すべてのリリースで検出結果を生みます。
- ビルドから記録する。マニフェストや完成した成果物のスキャンではなく、リリースビルドが実際に使ったものからインベントリを作ります。ビルド時SBOMには、どのロックファイルにも載っていないものも含め、ジョブが取得したものが含まれます。
-
コンポーネントをPURLで識別する。
pkg:npm/[email protected]のようなパッケージURLは、エコシステム、パッケージ、バージョンを正確に示します。OSVのエコシステムのアドバイザリのようにPURLをキーにしたアドバイザリと照合すれば、製品名からCPEを推測することで生じる誤った一致がなくなります。 - OSパッケージにはディストリビューションを考慮した照合を使う。Debianなどのディストリビューションは、アップグレードせずに出荷済みのバージョンへセキュリティ修正をバックポートするため、バージョン番号が上流の修正より古く見えることがあります。上流のバージョン範囲ではなく、ディストリビューション自身のセキュリティトラッカーと照合しましょう。
- 完全性を追跡する。インベントリが完全だと決めつけず、何かが見えなかった場合にそれを把握します。欠けたコンポーネントはノイズの多いコンポーネントより悪質です。検出結果がまったく出ないからです。
具体例。あるNode.jsサービスのロックファイルには、テストツールやビルドツールが依存するglobマッチングライブラリ[email protected]が含まれています。ロックファイルのスキャンは、4.0.8で修正された正規表現によるサービス拒否であるCVE-2024-4067を報告します。リリースジョブはnpm ci --omit=devで本番用の依存関係だけをインストールするため、micromatchは出荷されるビルドに入りません。そのビルドの記録には含まれず、検出結果がバックログに届くこともありません。CVEは本物ですが、この製品にとってこの検出結果は誤検知です。
ステップ2. 各検出結果を一度だけ数える
同じCVEがSCAツール、コンテナスキャナー、SBOMプラットフォームから届き、さらにそのライブラリを使うリポジトリの数だけ届きます。パッケージURL、バージョン、CVEという1つのキーで重複を排除しましょう。たとえば、pkg:npm/[email protected]とCVE-2024-45296の組み合わせは、いくつのツールが報告しても1件の検出結果です。
- スキャナーごとではなく、出荷する成果物ごとに1件として数えます。
- ビルドとリポジトリをまたいで集約し、共有ライブラリのCVEを40件のチケットではなく、どこにでも適用される1つの判断にします。
- 重複するスキャナーを統合します。シンプルなルールは、依存関係の検出結果は1つのSCAまたはSBOMの情報源から、イメージの検出結果は1つのコンテナスキャナーから、自社コードの検出結果は1つのSASTツールから得ることです。2つのツールが同じシグナルを報告するなら、出荷物により近い方を残します(SASTとSCAの比較)。
ステップ3. 出荷するものを減らす
出荷しない依存関係はすべて、対処する必要のない検出結果の発生源です。
- 使われていない依存関係を削除する。ほとんどのプロジェクトには、もう何もインポートしていないパッケージがいくつか残っています。
-
脆弱なパッケージを取り込んでいるパッケージをアップグレードする。Express 4.19.2は
[email protected]と[email protected]を固定しており、これらにはCVE-2024-45590とCVE-2024-45296があります。オーバーライドを使わずに単独で更新することはできません。2024年9月にリリースされたExpress 4.20.0は修正済みのバージョンに依存しているため、1回のアップグレードで両方が解消されます(推移的依存関係)。 - 最小限のベースイメージを使う。slimイメージやdistrolessイメージに含まれるOSパッケージは少ないため、該当するアドバイザリも減ります。イメージ固有の手段はコンテナスキャンで解説しています。
- 意図的に固定し、更新する。ロックファイルとダイジェストにより、ビルド間でインベントリが安定します。
- 既知の脆弱なバージョンを含むビルドをブロックする。ビルドを止めるポリシーゲートがあれば、脆弱なライブラリが、誰かがトリアージしなければならない検出結果になる前に締め出せます。
example-service
└─ [email protected] → upgrade to 4.20.0
├─ [email protected] CVE-2024-45590
└─ [email protected] CVE-2024-45296
ステップ4. 悪用可能性のコンテキストを加える
ステップ1〜3の後に残るものは本物です。そのうちどれが緊急かは、コンテキストが決めます。
- VEX。「影響なし」を理由とともにVEXステートメントとして一度だけ記録し、リリースや顧客をまたいで再利用します。顧客が自社製品を独自にスキャンした結果を転送してきた場合も、同じ記録で回答できます。PSIRTをスケールさせる方法と、返信テンプレートについてはサプライチェーン攻撃後に顧客へどう回答するかをご覧ください。
- 到達可能性は、ツールが提供している場合、自社コードが脆弱な関数を呼び出せるかどうかを示します。限界はあるものの役に立ちます(到達可能性分析)。
- 悪用のシグナル。CISA KEVは脆弱性が実際に悪用されていることを示し、EPSSは今後30日間に悪用される可能性を推定します。
- 露出度。インターネットに公開された製品は、プライベートネットワーク上の社内ツールより優先されます。
ステップ5. ポリシーに基づいて検出結果を担当者に振り分ける
- しきい値をポリシーとして書く。深刻度と悪用可能性のしきい値は、誰か1人が適用したダッシュボードのフィルターではなく、製品やリポジトリごとのポリシーとして定めます。
- 担当者を割り当てる。リポジトリやチームごとに割り当て、すべての検出結果に判断する人がいるようにします。
- 「修正なし」を明示的に判断する:有効期限付きで受容する、緩和する、またはコンポーネントを置き換える。修正のない検出結果を、判断のないまま放置してはいけません。
開発者が検出結果を無視する理由は4つあります。担当者がいない、コンテキストがない、期限がない、チャネルが違う。当社が話を聞いたチームからは、出力がノイズだらけで読めないため、エンジニアリングがスキャナーを止めてしまったという声も聞きます。それぞれの理由に対処しましょう。リポジトリごとの担当者、ステップ4のコンテキストの添付、ポリシーに基づく期限、そしてチームがすでに使っている場所への配信です。
ノイズ削減とリスクの隠蔽の違い
バックログが小さくなって良いのは、正しい理由で小さくなった場合だけです。
- 理由と有効期限のない抑制は、隠れた負債です。監査やインシデントで、理由を覚えている人が誰もいない状態で戻ってきます。
- 深刻度の下限は、誤った検出結果を取り除かずに隠します。「CVSS 7未満は対象外」とすると、CVSS 6の誤検知は消えますが、CVSS 9の誤検知は残ります。
- 修正しないという判断にはすべて記録が必要です。顧客も求めますし、EUのCyber Resilience Actのような規制も求めます。同法は製造者に、製品のサポート期間を通じて脆弱性に対処することを求めています。
測定方法
- スキャンごとではなく、出荷リリースごとの検出結果数。
- 対処された検出結果の割合:修正、緩和、または判断済み。
- VEXの記録付きで「影響なし」として閉じた件数と、記録なしで抑制した件数の比較。
- ビルドから担当者までの時間:新しい検出結果に担当者が付くまでの待ち時間。
- ツール間の重複率。
午後のうちにできる50件のサンプル調査。未解決の検出結果を無作為に50件選びます。それぞれについて、コンポーネントがリリースに含まれて出荷されるか、別のツールやリポジトリが同じ検出結果を報告しているか、一致が正しいか、自社製品で悪用可能か、修正が存在するか、担当者は誰かを記録します。その集計から、どのステップから始めるべきかがわかります。四半期後に同じサンプル調査をもう一度行いましょう。これらの数値について業界ベンチマークは引用しません。裏付けとなる一次情報源がないためです。
CRACIの役割
CRACIは、GitHub Actionsでビルドするソフトウェアについて、ステップ1と2、ステップ3のビルドゲート、そしてステップ4と5の一部を担います。
- インベントリ。CRACIはGitHubホストランナーを置き換え、各ジョブが実際に取得したパッケージを、コンポーネントごとのPURLとSBOMごとの完全性の状態とともに記録します。CRACIのSBOMに含まれるすべてのコンポーネントは、実際にビルドに含まれていたものです。この正確さはSBOMのコンポーネントについてのものであり、一致したCVEが自社製品に影響しない場合もあります。そのためにあるのがVEXで、CRACIはVEXに対応しています。
- 1つの検出結果、多数のビルド。検出結果はビルドとリポジトリをまたいで集約され、監視対象のSBOMは新しい脆弱性が公開されるたびに継続的に再評価されます。
- ゲート。ポリシーゲートは、特定のCVEを含むビルドを含め、検出結果に基づいてビルドをリアルタイムで停止できます。
- トリアージと割り当て。セキュリティチームはCRACIで検出結果をトリアージし、それぞれを修正を担当するチームに割り当てます。
- 通知。CRACIは脆弱性とその深刻度を関係者に通知します。
CRACIは到達可能性分析、SAST、MTTRダッシュボードを提供していません。機能の全体は脆弱性トラッキングをご覧いただくか、ビルドに実際に何が含まれているかを確認してください。
CRACIが適さない場合
- ノイズの大半が自社コードのSAST検出結果である場合。それはSASTのチューニングの問題です。
- バックログの大半が、出荷コードにある本物の悪用可能な検出結果である場合。それはノイズではなく、修正能力の問題です。
- 本番ワークロードのランタイムのコンテキストが必要な場合。CNAPPやランタイムセキュリティツールが答えます。
より広い計画はCVEが増え続けるときに何を自動化すべきかを、最新の数値はCVE公開件数のトレンドをご覧ください。
脆弱性ノイズの削減:よくある質問
脆弱性アラートの数を減らすにはどうすればよいですか?
発生源で、次の順に減らします。インベントリを出荷物と一致させる、パッケージURL、バージョン、CVEで検出結果の重複を排除する、出荷する依存関係を減らす、VEX、KEV、EPSSなどの悪用可能性のコンテキストを加える、残ったものを文書化したポリシーのもとで担当者に振り分ける。そのうえで優先順位を付けます。
スキャナーが数千件の脆弱性を報告するのはなぜですか? 重要なのはどれですか?
多くの場合、出荷しないコンポーネントを報告し、同じCVEをツールやリポジトリごとに報告し、一部の一致を誤って推測しているためです。重要なのは、リリースに実際に含まれるコンポーネントにあり、自社製品で悪用可能で、悪用が確認されているか悪用の可能性が高いものです。
複数のセキュリティツールの検出結果の重複を排除するにはどうすればよいですか?
すべての検出結果をパッケージURL、バージョン、CVEをキーにして、出荷する成果物ごとに1件として数えます。リポジトリをまたいで集約し、共有ライブラリを1つの判断にします。そのうえで、シグナルの種類ごとに1つのツールを割り当て、2つのスキャナーが同じことを報告しないようにします。
修正のない脆弱性は抑制すべきですか?
黙って抑制してはいけません。明示的に判断します。理由を書き、有効期限を付けてリスクを受容する、緩和する、またはコンポーネントを置き換える。そして修正が出たら見直します。理由と有効期限のない抑制は、隠れた負債です。
1年間誰も修正していない脆弱性は、まだノイズですか?
必ずしもそうではありません。古さはリスクについて何も語りません。出荷されていて悪用可能なら、判断と担当者が必要です。自社製品に影響しないなら、それをVEXステートメントとして記録し、再び現れないようにします。いずれにしても、判断のないまま放置してはいけません。
開発者がセキュリティの検出結果を無視しないようにするにはどうすればよいですか?
すべての検出結果に担当者、対処に必要なコンテキスト、文書化したポリシーに基づく期限を付け、チームがすでに使っている場所に届けます。まずノイズを取り除きましょう。検出結果の大半が重要でないチャネルは、開発者に読まれなくなります。
未解決の脆弱性は何件なら妥当ですか?
信頼できるベンチマークはなく、単純な件数は指標として不適切です。出荷リリースごとの検出結果数、対処された割合、理由を記録して閉じた割合、そして既知の悪用された脆弱性が出荷ソフトウェアで未解決のまま残る期間を追跡しましょう。
ビルドに実際に何が含まれているかを確認
デモを予約して、GitHub ActionsのワークフローをCRACIで実行してください。ビルドが実際に取得したもののSBOMと、そこに含まれる脆弱性を確認できます。
デモを予約