3
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

AIにホームラボの脆弱性管理を任せてみた — 検知から修正まで全自動化した話

3
Last updated at Posted at 2026-03-08

シリーズ: ホームラボ AI SOC 構築記
前回: AIにホームラボのセキュリティ監視を任せてみた — Sysdig × MCP × n8n で作る個人SOC

はじめに

前回の記事では、Sysdig Secure × MCP × n8n を使って、ホームラボにAI駆動のSOC(Security Operations Center)を構築した話を書きました。脅威検知の自動化は実現できた。では、次のステップは?

脆弱性は検知できる。でも、修正は?

Sysdig Secure が「Critical な脆弱性があります」と教えてくれるのは素晴らしい。でも、通知を受け取って「ふーん」で終わっていたら意味がない。検知 → トリアージ → 優先度判定 → 修正計画 → 承認 → 実行 → 検証。このライフサイクル全体を回す仕組みが必要だった。

結論から言うと、6フェーズ・59タスク・4つの n8n ワークフローを構築し、脆弱性の検知から修正まで一気通貫で自動化した。そして、その過程で「AIに承認ゲートを任せてはいけない」という、身をもって学んだ教訓がある。

「OK やって」 — この一言が、本番環境に未検証のイメージをデプロイしかけた事件の始まりだった。

vuln-mgmt-before-after.png


Before / After — 何が変わったのか

Before: 通知が来ても「あとで見る」

脆弱性管理の "Before" は、多くの組織で見覚えのある光景だろう。

  1. Sysdig Secure が脆弱性を検出する
  2. Slack に通知が飛ぶ
  3. 「あとで確認しよう」と思う
  4. 他のタスクに追われて忘れる
  5. 1ヶ月後、同じ脆弱性がまだそこにいる
  6. 「あれ、これ前も見たような…」

特にホームラボでは、専任のセキュリティチームなどいない。全部一人でやっている。通知は来るが、トリアージする時間も、修正を計画する時間も、実行する時間も限られている。結果として、見逃し・対応漏れ・優先度の判断ミスが常態化していた。

After: 検知から修正まで一気通貫

構築後のフローは、こうなった。

フェーズ 処理 担当
検知 Sysdig Automations が Critical + Exploit + Fix ありの脆弱性を検出 Sysdig Secure
通知 Slack #security-alerts に構造化通知 Sysdig Automations
AIトリアージ OpenClaw が CVSS/EPSS/Exploit/In Use を分析し、優先度を判定 OpenClaw (AI)
修正計画 AI が修正内容・リスク評価・ロールバック手順を生成 OpenClaw (AI)
承認 Telegram で構造化フォーマットによる承認(正規表現で厳密検証) n8n MCP ツール
実行 K8s REST API でイメージ更新(dry-run → 実行) n8n MCP ツール
検証 60秒間のヘルスチェック、異常時は自動ロールバック n8n MCP ツール

人間が関与するのは、修正計画の確認と承認の1ステップだけ。しかもその承認は、AIの「なんとなく OK」ではなく、正規表現による厳密なフォーマット検証を通過する必要がある。


アーキテクチャ全体像

vuln-mgmt-architecture.png

構築したシステムは4つのレイヤーで構成されている。上の図の通り、3つのデータフロー(リアルタイム検知・定期レポート/監視・半自動修正)がそれぞれ独立して動作する。

エンタープライズとの対比

「ホームラボでそこまでやるの?」と思うかもしれない。でも、やっていることの骨格はエンタープライズと同じだ。

機能 エンタープライズ ホームラボ (本構成)
脆弱性スキャン CNAPP / 脆弱性スキャナー Sysdig Secure
トリアージ セキュリティチーム OpenClaw AI
ワークフロー ITSM / チケット管理ツール n8n (OSS)
承認ゲート 変更管理プロセス (CAB) n8n MCP ツール (正規表現)
パッチ適用 構成管理 / IaC ツール K8s REST API 直接呼び出し
SLA 監視 専用ダッシュボード n8n 自動監視 + Telegram
レポーティング SIEM / BI ツール n8n 週次レポート + Sysdig Reporting

エンタープライズでは専任チームが回すフローを、Sysdig Secure + OSS の n8n + AI の OpenClaw を組み合わせることで、一人でも同等の脆弱性管理フローが構築できる。これがホームラボの醍醐味だ。


設計プロセス — 112件の指摘と5ラウンドのレビュー

この脆弱性管理フローの要件定義書は、v1.0 から v2.6 まで 16回の改訂 を重ねた。その中で特に効果的だったのが、5ラウンドのレビュープロセスだ。

レビューラウンドと発見件数

ラウンド レビュー種別 指摘件数 主な発見
Round 1 初回レビュー 17件 ファイル命名規則違反、セクション構造の不整合
Round 2 v2.0 レビュー 21件 Runtime/Pipeline トリアージ差分の未定義、AI プロンプト未更新
Round 3 クロスレビュー 21件 依存関係の誤り、変更履歴の順序ミス
Round 4 再レビュー 7件 テスト手順の分岐条件不足、MCP ツール名不統一
Round 5 実装リハーサル 46件 テスト用脆弱イメージ手順なし、SysQL 構文ミス、ヘルスチェック設計不備
合計 112件

「実装リハーサル」という手法

注目すべきは Round 5 の実装リハーサルだ。これは、要件定義書を「実際にこの手順で実装する」という視点で読み直すレビュー手法で、全体の 41%(46件/112件) の指摘がこのラウンドで発見された。

たとえば:

  • 「テスト用の脆弱なイメージをデプロイする手順が書かれていない」— テストは書いてあるが、テスト環境の準備手順がない
  • 「SysQL の構文が SQL 風になっている」— Sysdig の SysQL は MATCH 構文を使うグラフクエリ言語。SQL じゃない
  • 「ヘルスチェックの Phase 2(10分間の安定期監視)の設計が曖昧」— "簡略版" とだけ書いてあって、具体的な実装方式が不明

通常のレビューでは「論理的に正しいか」を見る。実装リハーサルでは「これで本当に手が動くか」を見る。この差分が 46件という数字に表れている。

教訓: 要件定義のレビューは "実装者の目線" で最低1ラウンド入れるべき


検知から監視まで — 基盤の構築

59タスクのうち44タスクで、検知・レポーティング・SLA監視の基盤を構築した。ここではポイントを絞って紹介する。

Sysdig Automations + AI トリアージ

基盤の核心は、Sysdig Secure の Automations 機能だ。

Automations は、Sysdig Secure 上で脆弱性の検出条件を定義し、条件に一致した場合に自動でアクションを実行する機能。ここでは以下の条件で Slack 通知を設定した:

  • Severity: Critical
  • Exploit: Public exploit available
  • Fix: Fix version available
  • 対象: nuc-home クラスタの Runtime 脆弱性

sysdig-automations-vuln-config.png

通知を受けた OpenClaw は、AI トリアージを実施する。ここで重要なのが Runtime と Pipeline の判定基準の違い だ:

判定要素 Runtime(nuc-home) Pipeline(tk-mini1)
In Use (Risk Spotlight) ✅ 最優先フィルタ ❌ 判定不可
CVSS
EPSS
Exploit 有無
Fix 有無

Runtime の脆弱性には Sysdig の Risk Spotlight 機能で「In Use」(実際にメモリにロードされているパッケージ)のフィルタが効く。これにより、インストールされているだけで使われていない脆弱なパッケージを除外できる。一方、Pipeline スキャンはポイントインタイムの静的解析なので、In Use の判定ができない。この差分を AGENTS.md のプロンプトに明記することで、OpenClaw が適切にトリアージできるようにした。

週次脆弱性レポート

週次レポートは n8n の独立 Cron ワークフローとして構築した。毎週月曜 10:00 JST に自動実行され、Sysdig REST API から脆弱性データを取得、集計し、Slack と Telegram に通知する。

設計のポイント: 脆弱性データの情報源は Sysdig Secure に一元化(Single Source of Truth)。n8n にはデータを保持しない。前週比較のためのサマリーだけ n8n の Static Data に保存するが、これは脆弱性ステータスではなくメタデータの例外的な保持にとどめている。

CLI Scanner + 定期スキャン

Mac Mini には Sysdig Agent(Linux カーネルモジュール)がインストールできない。代わりに Sysdig CLI Scanner を導入し、ローカルのコンテナイメージを Pipeline スキャンする。

# スキャン実行例
sysdig-cli-scanner --apiurl https://app.sysdigcloud.com \
  --json-scan-result /tmp/scan-result.json \
  docker.io/library/nginx:1.19.0

スキャン結果は Sysdig Secure にアップロードされ、Pipeline 脆弱性として管理される。日次の定期スキャンは launchd で自動化し、差分があればスキャン結果処理ワークフロー経由で Slack/Telegram に通知する。

SLA 監視

脆弱性には「いつまでに対応すべきか」という SLA(Service Level Agreement)がある。

Severity SLA
Critical 7日
High 30日
Medium 90日

SLA 監視ワークフローは毎日 09:00 JST に、Sysdig REST API で Runtime + Pipeline 両方の脆弱性をチェックし、SLA 超過があれば通知する。Critical の SLA 超過は Telegram にもエスカレーションされる。

n8n-wf5-sla-monitor-success.png

構築した n8n ワークフローの全体像がこちらだ。11のワークフローが稼働している。

n8n-workflow-list-vuln.png


"OKやって" 事件 — AI承認ゲートの落とし穴

ここからが、この記事のハイライトだ。

半自動修正フローの設計思想

最後の仕上げは、脆弱性の修正を半自動化すること。完全自動ではない。人間が承認するステップを必ず残す。

remediation-flow.png

フローの全体像はこうだ:

Step 1: 修正計画の AI 自動生成
OpenClaw がトリアージ済みの脆弱性情報(CVE ID、影響パッケージ、修正バージョン、CVSS/EPSS スコア)を分析し、修正計画を自動生成する。修正計画には以下が含まれる:

  • 修正対象(パッケージ名、現バージョン → 修正バージョン)
  • 修正カテゴリ(低リスク: パッチ更新 / 中リスク: マイナー更新 / 高リスク: メジャー更新)
  • 影響範囲(ワークロード名、Pod 数、ネームスペース)
  • ロールバック手順

Step 2: Telegram で承認を要求
生成した修正計画を Telegram に送信する。高リスクカテゴリ(メジャーバージョン更新)の場合は自動実行せず、手動対応を推奨する。

Step 3: 構造化フォーマットによる承認
ユーザーは 承認: CVE-XXXX-XXXXX / deployment/<name> の構造化フォーマットで返信する。正規表現で厳密に検証し、CVE-ID とワークロード名が修正計画と一致するかも確認する。

Step 4: Dry-run → 本番実行
承認後、まず K8s REST API の ?dryRun=All パラメータで変更内容をプレビューする。問題がなければ本番実行(イメージの PATCH)に進む。同時に修正可能なワークロードは 1 つに制限し、前の修正の検証完了後に次を実行する。

Step 5: ヘルスチェック(60秒間)
修正適用後、5秒間隔で Pod ステータスを K8s REST API で監視する。CrashLoopBackOff、ErrImagePull、ImagePullBackOff などの異常を検出する。全 Pod が Ready になれば成功。

Step 6: 自動ロールバック
ヘルスチェックで異常を検出した場合、またはタイムアウト(60秒)した場合、K8s REST API で元のイメージに自動ロールバックする。ロールバック自体が失敗した場合は緊急通知を送信する。

さらに、修正対象はホワイトリストで制限している。ネームスペースとワークロード名を事前に登録しておかないと、いくら正しいフォーマットで承認しても not_whitelisted で拒否される。意図しないワークロードへの修正を防ぐ安全装置だ。

設計段階では「AIに承認テキストを解釈させれば、柔軟に対応できるだろう」と考えていた。AGENTS.md(AI のプロンプト)に承認フォーマットを定義し、フォーマットに一致しない入力は拒否するよう指示する。合理的に聞こえる。

これが間違いだった。

"OKやって" — 何が起きたか

E2E テストで、以下のシナリオをテストした:

  1. テスト用の脆弱なイメージ(nginx:1.19.0)をデプロイ
  2. OpenClaw に「nginx の脆弱性を修正して」と依頼
  3. OpenClaw が修正計画を生成し、Telegram に送信
  4. ユーザーが 「OKやって」 と返信
  5. 期待する動作: 「正しいフォーマットで承認してください」とガイダンスを表示

実際に起きたこと: OpenClaw は「OK やって」を承認と解釈し、kubectl で nginx:1.19.10 へのイメージ更新を実行した。

構造化された承認フォーマット(承認: CVE-2021-23017 / deployment/vuln-test-nginx)を経由せずに、曖昧な日本語の一言で本番相当の操作が実行された。

なぜ起きたのか — AIの会話的性質 vs 構造化検証

根本原因はシンプルだ。AIは会話的な存在であり、人間の意図を "いい感じに" 解釈するのが仕事 だからだ。

AGENTS.md に「承認は 承認: CVE-XXXX / deployment/<name> のフォーマットで受け付けること」と書いても、AIにとってそれは「参考情報」に過ぎない。「OK やって」という入力を受け取ったとき、AIは以下のように推論する:

  • ユーザーは直前の修正計画に対して返信している
  • 「OK」は肯定の意思表示
  • 「やって」は実行の依頼
  • したがって、修正を承認している

論理的に正しい。しかし、セキュリティの観点では致命的に間違っている

承認ゲートに必要なのは、「ユーザーの意図を解釈する」ことではない。「決められたフォーマットに厳密に一致するかを検証する」 ことだ。これは AI の得意分野ではなく、正規表現の得意分野だ。

解決策 — n8n MCP ツールへの移管

解決策は明確だった。承認フォーマットの検証と K8s の修正実行を、AI から n8n の MCP ツールに移管する

approval-gate-comparison.png

具体的な変更内容:

機能 変更前 (AI ベース) 変更後 (コードベース)
承認フォーマット検証 AGENTS.md のプロンプト 正規表現(n8n MCP ツール)
K8s 操作 kubectl 直接実行 K8s REST API(n8n MCP ツール)
ヘルスチェック kubectl get pods K8s REST API(Pod ステータス監視)
ロールバック kubectl rollout undo K8s REST API(イメージ PATCH)

正規表現による厳密なフォーマット検証

const approvalRegex = /^承認:\s*(CVE-\d{4}-\d+)\s*\/\s*deployment\/([\w.-]+)$/;
const rejectionRegex = /^(拒否|却下)$/;

const text = input.approval_text.trim();

if (approvalRegex.test(text)) {
  // CVE-ID と deployment 名がリクエストと一致するかも検証
  const match = text.match(/承認:\s*(CVE-\d{4}-\d+)\s*\/\s*deployment\/([\w.-]+)/);
  if (match[1] !== input.cve_id || match[2] !== input.deployment) {
    return { status: "format_error", reason: "CVE-ID or deployment name mismatch" };
  }
  return { status: "approved" };
} else if (rejectionRegex.test(text)) {
  return { status: "rejected" };
} else {
  return { status: "format_error", reason: "invalid_format" };
}

この正規表現は曖昧さがゼロだ。「OK やって」「承認します」「いいよ」— どれも format_error として拒否される。承認するには、CVE-ID と deployment 名を含む完全なフォーマットを入力する必要がある。

kubectl 除去 → K8s REST API 直接呼び出し

もう一つの重要な変更が、OpenClaw から kubectl の実行権限を完全に除去したことだ。

変更前は、OpenClaw が kubectl set image で直接イメージを更新していた。つまり、AI がプロンプトのルールを無視すれば(「OK やって」事件のように)、何でも実行できてしまう状態だった。

変更後は:

  • OpenClaw はユーザーの返信テキストを n8n MCP ツール execute_remediation に渡すだけ
  • 実際の K8s 操作は n8n のコード内で実行(AI は関与しない)
  • K8s API への認証は ServiceAccount n8n-remediation の最小権限 RBAC
ユーザー → Telegram → OpenClaw (AI) → n8n execute_remediation (コード)
                                              │
                                              ├── 正規表現で承認検証
                                              ├── ホワイトリストで対象検証
                                              ├── K8s REST API: dry-run
                                              ├── K8s REST API: 実行
                                              ├── K8s REST API: ヘルスチェック (60s)
                                              └── 異常時: K8s REST API: ロールバック

AI の役割は「修正計画を生成する」ことと「ユーザーの返信を受け取って n8n に渡す」こと。判断と実行はすべてコードが担う。

n8n-mcp-integration-vuln.png

テスト結果

n8n MCP ツールへの移管後、以下の 7つのテストシナリオを全て Pass:

テスト 入力 期待結果 結果
曖昧な承認 「OK やって」 format_error ✅ Pass
不完全な承認 「承認します」 format_error ✅ Pass
CVE-ID 不一致 「承認: CVE-9999-9999 / deployment/vuln-test-nginx」 format_error ✅ Pass
正しい拒否 「拒否」 rejected ✅ Pass
ホワイトリスト外 正しいフォーマットだが対象外 NS not_whitelisted ✅ Pass
正常修正 nginx:1.19.01.19.10 success ✅ Pass
ロールバック 存在しないイメージへの更新 rollback (ErrImagePull) ✅ Pass

「OK やって」は、もう二度と通らない。


技術的深掘り — 構築で直面した壁

AGENTS.md 20,000バイト制限との戦い

OpenClaw の AGENTS.md(AI への指示プロンプト)には 20,000バイトの上限がある。SOC 運用のプロンプトで既に 11,000バイトを使っていたため、脆弱性管理で使える予算は約 9,000バイトだった。

59タスク分のルールと手順を 9,000バイトに収めるのは至難の業だ。解決策として:

  1. AGENTS.md はルールの要約のみ(〜2,000バイト)
  2. SOC-REFERENCE.md に詳細テンプレートを分離(制限なし)
  3. OpenClaw は必要に応じて SOC-REFERENCE.md を参照する

最終的に AGENTS.md19,607バイト(残り 393バイト)で収まった。ギリギリだ。

n8n CE の制限とワークアラウンド

n8n Community Edition (CE) 2.10.4 にはいくつかの制限がある。当初、承認ゲートを Webhook トリガー方式で実装する予定だったが、n8n CE では API 経由で Webhook ワークフローをアクティベートできないことが判明。

代替案として、MCP Integration の toolCode 方式を採用した。OpenClaw MCP Integration ワークフロー内に execute_remediation という toolCode ノードを追加し、全ロジック(承認検証、ホワイトリスト、K8s API 呼び出し、ヘルスチェック、ロールバック)を単一のコードブロックに実装した。

結果的に、この方式の方がシンプルで保守しやすかった。

cron 消失問題

OpenClaw の cron ジョブはメモリ上で管理されるため、ゲートウェイの再起動で消失する。これは SOC 運用構築時にも遭遇した問題で、以下の対策を実施:

  • バックアップスクリプトで cron 設定をエクスポート
  • ゲートウェイ再起動後に確認、必要に応じて再登録
  • 重要な定期処理(週次レポート、SLA 監視)は n8n の Schedule Trigger で管理(cron 消失の影響を受けない)

成果と数字

定量的成果

指標
総タスク数 59
完了タスク 59/59 (全フェーズ完了)
n8n ワークフロー 4つ (週次レポート, スキャン結果処理, SLA 監視, 半自動修正)
要件定義書バージョン v1.0 → v2.6 (16回改訂)
レビュー指摘件数 112件 (5ラウンド)
AGENTS.md サイズ 19,607 / 20,000 bytes
ヘルスチェック応答 60秒以内
ロールバック応答 約2秒 (ErrImagePull 検知 → ロールバック完了)

冒頭のアーキテクチャ全体像の通り、3つのデータフロー(リアルタイム検知・定期レポート/監視・半自動修正)が独立して稼働し、検知から修正までを一人で回せる体制が整った。

今後の展望

  • ヘルスチェックの高度化: 現在は Pod ステータス(Ready/CrashLoopBackOff 等)の確認のみ。HTTP エンドポイントの応答確認やリソース使用量の監視など、アプリケーションレベルのヘルスチェックを追加したい
  • 月次トレンドレポート: 脆弱性数の推移を可視化し、改善傾向を追跡

おわりに

「AI に任せれば大丈夫」— この思い込みが、"OKやって" 事件を引き起こした。

AI は素晴らしいトリアージ能力を持っている。修正計画の生成、リスク評価、自然言語による脆弱性照会。これらは AI の得意分野であり、積極的に活用すべきだ。

しかし、セキュリティゲート(承認検証)を AI に任せてはいけない。AI は会話的な存在であり、「いい感じに」解釈するのが仕事だ。「OK やって」を承認と解釈するのは、AI としては正しい判断だ。でも、セキュリティとしては致命的な判断だ。

AI は「考える」ために使い、「検証する」にはコードを使う。この原則は、ホームラボだけでなく、エンタープライズの AI 活用においても普遍的な教訓だと思う。

3
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?