AIエージェントが守るセキュリティ--少人数チームの脆弱性対策の常識を変えた話 (1/3) | 株式会社ストラテジーアンドパートナー
はじめにセキュリティ専任を用意出来る企業は希少攻撃者はAIを使い始めている攻撃者の優位性AIで防御を自動化する導入してどう変わったか通知設計で大事にしたことこの仕組み、セキュリティ以外にも使える...
https://www.wantedly.com/companies/strategy-jp/post_articles/1046432
第2回:システムの設計と実装の全体像
アーキテクチャ
SBOMとは何か
なぜSBOMが重要なのか
SBOMのメリット
SBOM運用の大変さ
2段階トリアージ——なぜLLMを2回呼ぶのか
キーワードマッチの工夫
LLMに何を渡しているか
Slack通知のノイズ制御
次回予告
第1回で紹介したCVE自動トリアージシステムの技術設計を解説します。
┌─────────────────────────────────────────────────────┐
│ プロジェクトファイル群 │
│ Docker コンテナ群(Webアプリケーション) │
│ │
│ syft(SBOM生成)→ keywords.txt / stack_context.txt │
└─────────────────────────────────────────────────────┘
↓生成されたSBOMを監視サーバに転送↓
┌─────────────────────────────────────────────────────┐
│ 監視サーバ(本番と分離) │
│ │
│ bot.py(systemd常駐) │
│ ├── NVD API 2.0 ─── 1時間毎にCVE取得 │
│ ├── キーワードマッチ(CPE構造 + description検索) │
│ ├── OpenAI API ──── スクリーニング → フルトリアージ │
│ ├── Slack API ───── 結果通知 │
│ └── データベース ──────── 処理済み記録・重複排除 │
└─────────────────────────────────────────────────────┘監視サーバを本番と分離しています。Slack BotのSocket Modeで外向きHTTPSのみで動作させています。そのため固定IPもポート開放も不要です。
アーキテクチャに登場したSBOMについて少し解説します。
SBOM(Software Bill of Materials)は、ソフトウェアを構成するすべてのコンポーネント(OSSライブラリ、フレームワーク、ランタイム等)とそのバージョンを一覧化した部品表です。ソフトウェア部品表のことですね。経済産業省は「食品の原材料名のようなもの」と例えています。食品の成分表示を見ればアレルギー物質が含まれていないか確認できるように、SBOMを見れば自社のソフトウェアに「危険な成分(脆弱性のあるパッケージ)」が含まれていないかを確認できます。
たとえば、新しいCVEが「next.js 15.0以前に影響」と公開されたとき、SBOMがあれば「自社は15.1.2を使っているから影響なし」あるいは「14.2.3を使っているから影響あり」と即座に判断できます。SBOMがなければ、まず「うちの環境でどのバージョン使ってたっけ…?」という調査から始まります。これも初動対応が遅れる要因の1つになります。
現代のWebアプリケーションは、90%以上がOSSの依存関係を含んでいます。package.jsonに書かれた直接の依存先だけでなく、その依存先がさらに依存しているライブラリ(推移的依存)まで含めると、実際に使われているコンポーネント数は数百になります。Log4ShellがLog4jというロギングライブラリの依存を通じて広範に影響したのは、まさにこの推移的依存の問題です。
SBOMがあると、この「自分たちが何を使っているか」が明確になります。私たちのCVEトリアージBotでは、このSBOMをLLMに渡すことで「このCVEは自社に影響するか?」という判断の精度を飛躍的に上げています。
脆弱性対応の速度が変わる
新しいCVEが公開されたとき、SBOMがあれば「自社に影響するか」の判断が秒単位でできます。SBOMがないと、環境に入り影響ありそうなコンポーネントのバージョンを1つずつ調べることが必要になりますので、それだけで攻撃者に遅れをとります。
自動化の土台になる
SBOMは機械可読なフォーマット(SPDX, CycloneDX等)で出力できるため、人間が目視で確認するだけでなく、LLMやスクリプトによる自動照合に使えます。私たちのBotではSBOMからキーワードリストを自動生成し、LLMのプロンプトにも渡しています。
良いことばかり書きましたが、運用には現実的な課題がありました。
「一度作って終わり」ではない SBOMはビルドやデプロイのたびに更新が必要です。依存パッケージは日々更新されるので、古いSBOMはその時点で嘘になります。CI/CDに組み込んで自動更新するのが理想ですが、私たちはまだ手動で定期的に生成している段階です。
ノイズが多い syftで生成した生のSBOMには、OSのベースパッケージや汎用的な名前のライブラリ(buffer, link, send等)が大量に含まれます。これらをそのままCVE照合に使うと誤検知だらけになるため、除外リストの調整が必要です。完全な自動化には至らず、人間によるチューニングが残ります。
網羅性の壁 Dockerコンテナ内のパッケージはsyftで拾えますが、コンテナ外のミドルウェア(ホストOS側のミドルウェア等)は別途管理が必要です。完全なスタックの可視化には、複数の手法を組み合わせる必要があります。
SBOMは「導入したら安心」ではなく、継続的にメンテナンスしていくものです。ただ、その大変さを差し引いても、「自分たちが何を使っているか分からない」状態で脆弱性対応することのリスクのほうがはるかに大きいと実感しています。
全CVEをフルトリアージにかけるとAPI料金が跳ね上がります。そこで、軽量なスクリーニング(第1段階)で「影響なし」を弾き、影響ありだけフルトリアージ(第2段階)にかける仕様にしています。
スクリーニングLLMはJSON出力で{"affected": true/false, "reason": "..."}を返すだけにしています。トークン消費はフルトリアージの1/10以下です。結果、フルトリアージは1日0〜2件。CVEの量にもよりますが月額1~2ドル程度で収まっています。
NVDのCPE(構造化された製品名データ)と、descriptionフィールドのテキスト検索を併用しています。
新しいCVEにはCPEが未登録のケースが大半(弊社の調査では直近24時間で66件中0件)なので、テキスト検索が実質的なメインとなります。短いパッケージ名(wsなど)は誤検知を起こしやすいので、5文字未満の単語に単語境界マッチ(\bws\b)を適用して防いでいます。
キーワードリストはSBOMツール(syft)でDockerコンテナから自動生成します。
スクリーニングとフルトリアージでLLMに渡す情報量を変えています。
スクリーニングにはCVEの基本情報+SBOM+サービス仕様書を渡します。
フルトリアージではさらにCVSSベクタ、参考URL、サービス仕様書の攻撃面(外部入力を処理するコンポーネント、認証不要エンドポイント)を追加します。
サービス仕様書を含めることで、「このエンドポイントは認証なしで外部からアクセスできるため、攻撃条件を満たす」といったプロジェクトに最適化された文脈で具体的な判断が可能になります。LLM活用の壁の1つに「回答が汎用的で役に立たない」「結局人間が自社の文脈で解釈する必要がある」というものがありますので、ドメイン情報をLLMに渡すやり方はLLMの有効性を高める良いアプローチでした。
初期バージョンでは影響なしも1件ずつ通知していましたが、チャンネルが影響無し通知ですぐ埋まるため、日次サマリ方式に切り替えました。
影響なしCVEはデータベースにNOT_AFFECTEDステータスで記録し、summary_notifiedフラグで未通知分を管理。朝9時と夕方19時にまとめて通知します。データベース永続化なのでBot再起動でも未通知分は失われません。
影響ありの通知はSlack Blocksの先頭セクションにメンションを挿入しています。textパラメータだけにメンションを入れるとチャットUI上で見えない(プッシュ通知にしか反映されない)Slack APIの罠があるので注意が必要です。
第3回では運用で得られた知見と、このAIエージェント防御パターンを他の領域に応用する可能性について解説します。