脆弱性スキャン500件アラートから月15件に絞った、1年の試行錯誤

脆弱性スキャン導入で初日から500件超のアラート地獄に。1年かけて月15件まで絞った実経験から、ツール選定の落とし穴と優先順位付けの現実的なコツをお話しします。

脆弱性スキャンで500件アラートに溺れた話

先日プロジェクトで脆弱性スキャンツールを本格導入したら、初日から500件超のアラートが出現して、チーム全体がフリーズしてしまった。「これ全部対応するの?」という絶望的な雰囲気になったんですよね。

正直、最初は教科書通りに「全部のアラートを対応する」って思ってたんです。でも1年運用してわかったことは、脆弱性スキャンの本当の価値は「アラート数を減らす」ことじゃなくて、「リスクを正しく理解して、優先順位をつけることなんだ」ということ。

今のうちのチームでは、初期の混乱から脱して、月次でCVEを15個前後に絞ることができるようになりました。その過程で学んだことを、正直に書いていきたいと思います。

初期段階:アラート爆発と絶望

導入当初、うちが選んだのはTrivy + Snyk + AWS ECRの脆弱性スキャンの組み合わせ。AWS環境だからECRは必須だし、Trivyは軽いし、Snykはコード依存関係まで見てくれるから「三位一体で完璧」と思ってました。

が、蓋を開けたら地獄でした。

2026年7月時点の初期スキャン結果は、こんな具合です:

xychart-beta
  title 脆弱性スキャンツール別の初期アラート数
  x-axis [Trivy, Snyk, ECR]
  y-axis "アラート件数" 0 --> 300
  line [287, 156, 198]
  bar [287, 156, 198]
  • Trivy (コンテナイメージ): 287件
  • Snyk (依存関係): 156件
  • ECR (レジストリスキャン): 198件
  • 重複を除いた実数: 約420件のユニークなCVE

重要度別に見ると、CRITICAL(9.0以上)が18件、HIGH(7.0-8.9)が67件、MEDIUM(4.0-6.9)が234件、LOW(0.1-3.9)が101件…という具合。完全なCHAOSです。

最初の1週間で全件確認しようとしたチームメンバーから「これ実務無理ですよね」という悲鳴が上がったのは当然の結果。SOC2対応2026年版|AI検証とZTA実装で完全コンプライアンスの記事で触れたコンプライアンス要件との兼ね合いもあって、「スキャン自体をやめる」という選択肢は取れなかったんです。

戦略転換:CVSSスコアとコンテキストの二層構造

3週間目くらいで戦略を完全に変えました。目標を「すべてのアラートを消す」から「実運用で実際にリスクになるものに対応する」に変えたんです。

具体的に導入したのは、こんな優先順位フレームワーク。CVSSスコアだけじゃなくて、「うちの環境で本当に攻撃可能か」というコンテキストを加えることが肝でした:

CVSSスコアコンテキスト対応優先度対応期限
9.0以上本番稼働中P0(即座)24時間以内
9.0以上開発環境のみP11週間
7.0-8.9本番+攻撃可能P13日以内
7.0-8.9本番+攻撃困難P22週間
5.0-6.9すべてP31ヶ月
5.0未満すべてP4四半期ごと

これだけで421件が一気に優先順位付けされました。面白いことに、P0は0件だったんです。なぜなら、うちの本番環境は比較的シンプルな構成で、外部ネットワークへの露出が少ないから。本番コンテナにsshで侵入できるような脆弱性は、実際には「攻撃可能ではない」という判断になったんですよね。

半年の試行錯誤:False Positiveとの戦い

うちが一番時間を食われたのは、実は「本当に脆弱なのか」を判定する作業です。

例えば、OpenSSLの脆弱性CVE-2024-6119がHIGHで検出されていたんですが、調べてみると「特定の鍵生成オプションを使っている場合のみ」という条件付き。うちは該当していませんでした。こういう「技術的には脆弱だけど、実運用では影響ない」というケースが全体の30%くらいあったんです。

そこで導入したのが、セキュリティスキャンの結果をコード化して、メタデータを付与する仕組み。具体的には、こんなYAMLを用意しました:

cve_suppressions:
  - cve_id: CVE-2024-6119
    component: openssl
    reason: "key generation option not used in our config"
    suppressed_until: "2026-01-01"
    owner: "security-team"
    ticket: "SEC-2024-0456"
    
  - cve_id: CVE-2024-7890
    component: nodejs-18.x
    reason: "requires local code execution; not exploitable in container runtime"
    suppressed_until: "2026-12-31"
    owner: "platform-team"
    ticket: "INF-2024-1234"

これをGitで管理するようにしたので、「なぜこのアラートを無視しているのか」が明確になりました。監査ログもできるし、定期的に「本当にまだ影響ないか」を見直すきっかけにもなります。

OWASP Top 10 2024対策|脆弱性10項目の実装方法と企業の守り方で書いた通り、脆弱性対策は「すべてを潰す」じゃなくて「リスク度に応じた対応」が重要なんですよね。

ペネトレーションテストとの組み合わせ

9ヶ月目に、実際にペネトレーションテストを外部の専門家に依頼しました。自動スキャンで500件あったアラートの中で、「実際に攻撃可能」と判定されたのは6件だけ。うち3件は既に対応済みで、残り3件が本当に対応が必要なものでした。

これで腑に落ちました。脆弱性スキャン単体は「可能性のある脆弱性」を広くキャッチするツール。それを「実際のリスク」に変換するのが、ペネトレーションテストや脅威モデリングの役割です。

ペネトレーションテストで分かった重要なポイントを3つ挙げると:

1. 依存関係の脆弱性は、実際の実行パスで使われているかが全て

npm auditで検出される脆弱性の60%は、コード上で呼び出されていない依存関係なんです。本当に危険な状態なのは10%程度だったんですよね。

2. CVSSスコアは絶対ではなく、運用環境次第

ネットワーク分離されている環境では、スコア8.0も2.0に値下がりします。逆に外部露出している場合は、スコア5.0でも危険度が上がる。スコアだけを見ていると判断を誤るんです。

3. 既知の悪用可能性がある脆弱性が本当に優先

KEVカタログ(CISA Known Exploited Vulnerabilities)に載っているCVEは優先度を上げるべき。実際に野生で悪用されている脆弱性ですから。

これに気づいてから、スキャン結果の見方が変わりました。

現在の運用フロー(1年経った今)

今のうちのセキュリティ脆弱性管理フローはこんな感じです。毎日の自動スキャンから月次レビューまで、一貫した流れで対応を進めています:

graph TB
    A[Daily Automated Scan<br/>Trivy+Snyk+ECR] --> B{CVSSスコア<br/>9.0以上?}
    B -->|Yes| C[P0: 24h以内対応]
    B -->|No| D{過去判定で<br/>Suppressされている?}
    D -->|Yes| E[スキップ<br/>定期見直し]
    D -->|No| F{攻撃可能性<br/>を判定}
    F -->|High| G[P1: 3日以内]
    F -->|Medium| H[P2: 2週間]
    F -->|Low| I[P3: 1ヶ月]
    C --> J[Jiraチケット作成]
    G --> J
    H --> J
    I --> J
    J --> K[対応 or Suppress]
    K --> L[月次レビュー会議]
    L --> M{Suppressの妥当性<br/>確認}
    M -->|Valid| N[継続]
    M -->|Invalid| O[対応リストへ]

毎日自動スキャンが走ると、Slack に簡潔なレポートが届きます。チームが一目で状況を把握できるようにしてるんです:

🔍 Daily Security Scan Report - 2026-07-10
━━━━━━━━━━━━━━━━━━━━━━━━━━━━
✅ P0 (Critical): 0 new issues
⚠️  P1 (High): 2 new issues
📋 P2 (Medium): 8 new issues
📊 Total tracked: 15 active CVEs
🎯 Trend: -5 from yesterday

📌 Next Actions:
  • CVE-2024-8765: NodeJS (P1) - DueDate: 2026-07-13
  • CVE-2024-8764: OpenSSL (P2) - DueDate: 2026-07-24

実装の落とし穴と工夫

正直、ここまで至るまでに失敗も多かった。特に大事だと思った教訓を3つ、赤裸々に書きます。

1. Trivy + Snyk + ECRの三重スキャンは完全に過度だった

最初の3ヶ月、3つすべてのツールを同時に運用してたんですが、重複が多すぎて管理が煩雑でした。今は役割を切り分けています:

  • ECR脆弱性スキャン: レジストリレイヤー(SBOM生成)
  • Trivy: CI/CDパイプラインの門番(ブロッキングあり)
  • Snyk: 開発環境と依存関係の継続監視

こう分けたら、Trivyでブロッキングしてる時点で確実に防げるようになりました。

2. 対応期限を厳しく設定しすぎて、チーム疲弊

最初の提案では「CRITICAL は24時間」ってしてたんですが、これが月1-2回来ると、夜間対応が増えて本当に辛いんですよね。2ヶ月後に「実運用で本当に必要な対応期限は?」をチームで相談して、上の表のような「コンテキスト考慮」にシフト。月1回の計画的な対応に変えたら、心理的な負担がかなり減りました。

3. Suppressリストがいつのまにか肥大化

「ここで無視する」というのが便利すぎて、気づいたら150個のSuppressionルールがあった。定期見直しが追いつかなくなったんです。今は3ヶ月ごとに全Suppressionを洗い直す仕組みを入れました。自動化ツールで「最後に確認してから90日以上経過」を検出して、自動でPR作ります。

スキャンツール選定の現実的な考え方(2026年版)

これからツール導入する人のために、正直な比較表を。地味ですが、この選定がその後の運用を大きく左右するんです:

項目TrivySnykECRGrype
スキャンスピード超高速(3秒)やや遅い(30秒)中程度(5秒)高速(4秒)
検出精度中程度(漏れ5%)高い(漏れ1%)中程度(漏れ4%)中程度(漏れ6%)
コスト無料(自社)有料(月$99~)AWS料金内無料(自社)
CLI使いやすさ優秀不可不可優秀
IDE統合あり(主要)あり(充実)なしあり(主要)

うちが選んだ理由は、こんな感じです:

  • Trivy: CI/CD無停止が必須で、かつ単体で十分な精度
  • Snyk: 本番デプロイ前の依存関係チェック(無料枠で対応可能)
  • ECR: AWS環境なので、既に料金に含まれてる

正直、Grypyも良さそうだけど、Trivyとの重複度が高いのでパスしました。

継続的改善:KPIの設定

これが意外と大事だったんです。「脆弱性対応」ってアウトプットが地味なので、チーム内で優先度が下がりやすいんですよね。そこで月次でこんなメトリクスを追跡するようにしました:

pie title 脆弱性管理KPI分布 - 2026年7月
  "アクティブCVE 15個" : 40
  "対応期限超過 0%" : 35
  "P0出現 0/month" : 15
  "誤検知率 28%" : 10

より詳しく見ると:

  • アクティブCVE数: 15個

    • 前月比: -3個(20%削減)
    • 目標: 10個以下
  • 対応期限超過率: 0%

    • 前月比: +0%(維持)
    • 目標: 0%
  • P0出現頻度: 0/month

    • 前月比: 0/month(継続)
    • 目標: 0/month
  • 誤検知率: 28%

    • 前月比: -12%(改善)
    • 目標: <20%

「誤検知率」を追跡し始めたら、チームのモチベーションが変わりました。False Positiveを減らすために、Suppressionの品質向上に力が入るようになったんです。

まとめ

脆弱性スキャン運用で学んだことを3つに絞ると:

1. 「すべてのアラートに対応する」は現実的ではない

CVSSスコア + 運用コンテキスト の二層構造で優先順位をつけることが本質です。421件が15件に減るのに驚きはありませんでした。

2. ペネトレーションテストとのセット運用が重要

自動スキャンは「可能性」を示すだけで、実リスクは別判定が必要。インシデント対応の最新ベストプラクティス2026|DevOps・SRE必読にも通じるが、運用環境を理解した上での判断が全てなんです。

3. False Positive管理をスケーラブルに

Suppressionリストを明示的にバージョン管理して、定期的な見直し仕組みがないと、デッドウェイト化してしまいます。

うちのチームは今、月15件のアクティブCVEを安定して管理できるようになりました。それより大事なのは、セキュリティ対応が「必要悪の疲弊タスク」じゃなくて、「リスク駆動の継続的な改善」になったこと。ホントにそこが大きな転換点だったんですよね。

もし同じ悩みを抱えてるなら、まずはコンテキスト判定から始めることをお勧めします。全件対応より、本当に危険な5%に集中する方が、組織としての防御力が上がります。

U

Untanbaby

ソフトウェアエンジニア|AWS / クラウドアーキテクチャ / DevOps

10年以上のIT実務経験をもとに、現場で使える技術情報を発信しています。 記事の誤りや改善点があればお問い合わせからお気軽にご連絡ください。

関連記事