Cloudflare の security-audit スキル:Claude Code による敵対的 AI セキュリティ監査(2026年)
- 「Claude に脆弱性を見つけさせる」だけでは自信満々のゴミが生まれる理由と、ハンターと検証者の間の権力分立がそれをどう解決するかを説明する
- 6 つのフェーズを順に追い、architecture.md から NEEDS-VALIDATION.md まで、各フェーズが生み出す成果物を挙げる
- findings.json を正しく読む:confirmed、needs_validation、rejected がそれぞれ何を必要とし、なぜ confirmed のレコードだけが深刻度を持つのか
- そのルールを満たすサンドボックス内で Claude Code からスキルを実行し、出力を機械的に検証し、カバレッジのために再実行する
- 予算を立てる:トークン請求額の見え方、スキルがハンターの起動を拒否するルール、そして実行を手頃に保つ 3 つの方法
Cloudflare は 2026 年 9 月中旬に 1 つのスキルをオープンソース化し、それは GitHub で最も急成長するリポジトリになりました:cloudflare/security-audit-skill は 9 月 21 日時点で 18.5k スターに達し(1 日で 2.4k 増加)、9 月 17 日にはすでに 211 ポイントの Hacker News スレッドを集めていました。これが重要な理由はスター数ではありません。このスキルが、Cloudflare が 6 月に説明したフリート全体の脆弱性ハーネス、すなわち 128 のリポジトリにわたって実行され 7,245 件の対処可能な発見を生み出したハーネスの種だからです。公開されたスキルは、Claude Code で今日から実行できる単一リポジトリ版です。
それが何であるかを正確に述べておく価値があります。バイナリもルールエンジンも独自のモデルもありません。SKILL.md と 14 のハンティングガイド、そして依存関係ゼロの 2 つの Node バリデータです。それが行うことはすべて、あなたのエージェントに狭い任務を持つ隔離されたサブエージェントを生成させ、別のエージェントがそれを破ろうと試みるまで出力を受け入れないことによって実現されます。
「脆弱性を見つけて」だけでは失敗する理由
Cloudflare の 6 月の記事には、設計全体を説明する一文があります:制約のないエージェントは「自分のエクスプロイトが動くようにソースコードを編集し、そして自分が作ったばかりのバグを意気揚々と報告する」。そして対になるルール:「ハンターが自分の宿題を自分で採点することを許されれば、自分の出力すべてを自信を持って検証してしまう」。
これが、ワンショットの「私のリポジトリを監査して」プロンプトすべての失敗モードです。理論を組み立てるのに 8 万トークンを費やしたモデルは、その理論を判定させたい最後のモデルです。スキルの答えは構造的なものです:
- ハンターは発見を登録できません。 ハンターは候補を返し、対象のソース、アーキテクチャノート、台帳、findings ファイルを編集することは禁じられています。
- 検証者はハンティングできません。 新しい検証者は 1 つの候補、アーキテクチャの事実、スキーマだけを受け取り、それ以外は何も、他の検証者の結論すら受け取りません。その仕事は反証することです。
- 決定論的なコードが受け入れない限り、何も保持されません。 親エージェントが共有ファイルを書き、
validate-findings.cjsとvalidate-coverage-ledger.cjsがスキーマに違反するものを拒否します。
Cloudflare の社内版はさらに進んで、発見とは異なるモデルを検証に使います。別の重みが偏りのないセカンドオピニオンを与えるという考えからです。公開スキルはそれを強制しませんが、検証者サブエージェントを別のモデルにルーティングすることを妨げるものは何もありません。
6 つのフェーズと、それぞれが残すもの
| フェーズ | 実行者 | 出力 |
|---|---|---|
| 1. 偵察 | 4 つの並列リサーチエージェント(スタックとビルド;プリンシパルと認証;エントリサーフェスとシンク;オフラインでテスト可能なもの)が事実のみを返す | architecture.md(約 1,000 語)とシード済みの coverage-ledger.json |
| 2. カバレッジ主導のハンティング | 隔離されたハンターのウェーブ、それぞれ 1 つ以上の台帳ユニットを担当;各ウェーブ後にカバレッジ批評者 | proposed_verdict 付きの候補、ユニットの処理結果、堅牢化メモ、新たに発見されたギャップ |
| 3. 候補の検証 | 一意な候補フィンガープリントごとに 1 人の新しい検証者 | 候補ごとの決定:confirmed、needs_validation、rejected のいずれか |
| 4. 構造化出力 | 親のみ | フィンガープリント順にソートされ、スキーマ検証済みの findings.json |
| 5. 独立したレコード検証 | confirmed または needs_validation のレコードごとに 1 人の新しい検証者 | verified または replace;重要な置き換えには2 人目の新しい検証者が付く |
| 6. 対象中立なレポート | フェーズ 5 通過後の親 | REPORT.md、FINDINGS-DETAIL.md(medium 以上のみ)、NEEDS-VALIDATION.md |
すべては ~/security-audit-skill/<repo-name>/run-<N>/ の下に置かれ、エージェントごとに agents/<id>/scratch/ と agents/<id>/artifacts/ ディレクトリがあります。共有ファイルを書くのは親だけです。
カバレッジ台帳は、ほとんどの人が見落とすメカニズムです。ユニットとは、エントリサーフェス、信頼境界、サブシステム、攻撃クラスの 1 つの重要な組み合わせであり、リポジトリ内の開始パスを伴います。ユニットは planned、in_progress、blocked、covered、candidate の状態を移り、各状態にはどの証拠フィールドを埋めなければならないかのルールがあります。カバレッジ批評者はウェーブ後に台帳全体を読み、マッピングされていないエントリポイント、チェックされていない並列パス、正当化されていない除外を探します。ユニットを再オープンすることはできます(以前の試行はアーカイブされます)が、発見を提案することは決してできません。これが再実行を加算的にするものです:2 回目の実行は、1 回目が blocked のまま残したり再オープンしたりしたユニットを拾い、すべてを監査し直すことはありません。
3 つの判定と、なぜ 1 つだけが深刻度を持つのか
スキーマは各判定が使用できるフィールドについて厳格で、バリデータがそれを強制します。
| 判定 | 意味 | 必須 | 禁止 |
|---|---|---|---|
confirmed | サンドボックス内でソースから独立して再現済み、観測された最小限の影響のみ | root_cause, intended_behavior, trace(エントリポイントからシンクまで), evidence, conditions, execution, remediation, severity, confidence | claimed_root_cause, blockers, validation_plan, reason |
needs_validation | ソースに裏付けられているが、ローカルでは解決できない 1 つの正確な事実(デプロイ設定、オーナーのみの設定)に阻まれている | claimed_root_cause, trace, evidence, blockers, validation_plan | severity, execution, remediation |
rejected | 検証者が反証した | claimed_root_cause, trace, evidence, reason | severity, execution, remediation, blockers |
3 つの帰結が導かれます:
needs_validationの発見には設計上、深刻度がありません。 それは「medium」ではなく、コードオーナーへの質問であり、それに答えるための正確な計画を伴います。NEEDS-VALIDATION.mdが存在するのは、そのリストが脆弱性リストと誤解されないようにするためです。- 深刻度には、チェックリストの不備ではなく、実証された影響が必要です。
SKILL.mdの較正:critical は未認証のコード実行、完全なデータアクセス、またはアカウント乗っ取り;high は明示的な制御の完全な突破(認証バイパス、テナント間アクセス);medium は限定的な影響範囲または稀な前提条件;low は秘密でない情報の開示;informational は影響が最小限の確認済みの観測。「ベストプラクティスの欠如」は明示的に発見ではありません。 - クリーンな実行はゼロを報告します。 レポートガイドは、釣り合いの取れたレポートには confirmed の発見がまったくないこともあり、その場合はそう明言しなければならないと述べています。あなたの実行が小さなサービスで 20 件の critical を「発見」したなら、サービスを疑う前にサンドボックスの設定を疑ってください。
このセクションの読者にとって、AI/LLM ハンティングガイドは最も鋭い部分です。その冒頭のルール:「プロンプトインジェクションだけでは発見にならない。コードレベルの境界の失敗を要求せよ。」 ハンターは攻撃者、影響を受けるプリンシパル、実行アイデンティティ、そして未承認のアクションまたは開示を、攻撃者が制御する入力から副作用までのソーストレースとともに示さなければなりません。ハンターに追わせるパターンは、私たちのプロンプトインジェクションと MCP ツールポイズニングのページにあるものですが、コードの欠陥として枠付けされています:ハンドラ側の検証なしに SQL やシェルに到達するツール引数、最小権限ではなく完全な認証情報を継承するサブエージェント、認可として扱われるツールの説明、エンコードなしに HTML やコマンドにレンダリングされるモデル出力、過度に広いキャッシュキーによるテナント間のコンテキスト漏れ。モデルを説得して失礼なことを言わせても、カウントされません。
サンドボックスのルールは助言ではない
SKILL.md は、対象が制御するあらゆるコード(テスト、フィクスチャ、プロジェクト自身のビルド)を、外部ネットワークなし、せいぜい隔離されたループバック名前空間、読み取り専用の対象ソース、scratch/ に限定された書き込み、そして厳格な CPU・メモリ・プロセス・ファイルサイズ制限を備えた OS 強制のサンドボックス内で実行することを要求します。検証者は、サンドボックスが利用できない場合、候補は単に未検証のままにするよう指示されています。scratch/ から保持される artifacts/ への昇格は、シンボリックリンク、複数リンクされたファイル、アーカイブ、再帰的コピーを拒否し、パスによる再オープンを一切行いません。
これは私たちの攻撃を受けるコーディングエージェントのページと同じ脅威モデルを内側に向けたものです:監査しているリポジトリは敵対的かもしれず、そのテストスイートはあなたがこれから実行するコードです。Claude Code では、これは日常のシェルで実際の環境変数を使うのではなく、サンドボックスと認証情報マスキングの制御をオンにして監査を実行することを意味します。Cloudflare 自身のハーネスからの落とし穴が 1 つ、コンテナ内に Docker をネストする場合に当てはまります:seccomp=unconfined と apparmor=unconfined が必要で、「さもなければ静かに失敗する」のです。
- npx skills add https://github.com/cloudflare/security-audit-skill --skill security-audit。skills CLI(vercel-labs/skills)は Claude Code なら .claude/skills/ に、Codex、Cursor、Gemini CLI なら .agents/skills/ に配置します。グローバルインストールには -g を、1 つのエージェントを対象にするには -a claude-code を追加します。実行する前に SKILL.md を読んでください:それはあなたがこれから実行する契約です。
- サンドボックスと認証情報マスキングをオンにし、環境に本番の認証情報を置かず、ネットワークの送信先をモデルプロバイダーに限定して、対象リポジトリで Claude Code を起動します。このスキルには並列サブエージェントを生成できるエージェントが必要です。Claude Code の Agent ツールはその条件を満たします。
- 「security audit this codebase」または「find security vulnerabilities in ./src」と言います。より狭い質問(「この JWT チェックは安全?」)は代わりにガイダンスモードをトリガーし、実行ディレクトリを作らずに回答します。初回の実行では、モノレポのルートではなく、境界の明確な 1 つのディレクトリを指定してください。
- すべては ~/security-audit-skill/<repo>/run-1/ の下に現れます。architecture.md は数分以内に存在するはずです。coverage-ledger.json はユニットごとに成長し、findings.json はフェーズ 4 の後にのみ現れます。偵察の後に何も置かれていなければ、エージェントが実行できるサンドボックスを持っているか確認してください。
- node <skill-dir>/validate-findings.cjs run-1/findings.json と node <skill-dir>/validate-coverage-ledger.cjs run-1/coverage-ledger.json を実行します。スキルはこれらを自身で実行しますが、自分で実行することが、セッション制限で途中で打ち切られた実行を捕まえる最も安価な方法です。
- 各ブロッカー(あなたのデプロイに関する質問として表現されています)に答え、レコードを昇格させるか破棄します。それから再度実行します:台帳の prior_status フィールドにより、2 回目の実行は最初からやり直すのではなく、blocked および再オープンされたユニットを対象にします。Cloudflare 自身のデータによれば、1 回の実行で見つかるのは、繰り返し実行で見つかるもののおよそ半分です。
トリガーフレーズとバリデータのコマンド
# Full audit (creates ~/security-audit-skill/<repo>/run-N/) security audit this codebase find security vulnerabilities in ./src # Guidance mode (no run directory, no sub-agent fleet) is the session cookie handling in auth/session.ts safe against fixation? # After a run: mechanical checks, zero dependencies beyond Node node .claude/skills/security-audit/validate-findings.cjs ~/security-audit-skill/<repo>/run-1/findings.json node .claude/skills/security-audit/validate-coverage-ledger.cjs ~/security-audit-skill/<repo>/run-1/coverage-ledger.json # What the schema hard-limits (validator rejects beyond these) # findings.json: 5 MiB, 1,000 findings, 64 nesting levels # coverage-ledger.json: 5 MiB, 10,000 units, 1,000 entries per collection
コストと、それを手頃に保つ方法
HN スレッドの大半は請求額の話です。あるユーザーは「中規模のコードベースで 100 万トークンを無駄に投げた」と報告し、別のユーザーは実用上の上限を 15 万トークン、つまり注意力が劣化する「愚鈍ゾーンに入り始める」ところに置きました。これらは測定ではなく逸話ですが、設計の形と一致しています:4 つの偵察エージェント、ハンターのウェーブ、候補ごとの検証者、ウェーブごとの批評者、そして生き残ったレコードごとの 2 人目の検証者。Cloudflare のフリートの数字が正直なスケールを示しています:標準的な 3 万行のリポジトリは約 100 件の生の発見に対して 3〜4 時間かかり、フリート全体では生の候補の 58% が検証を生き残りました(20,799 件中 12,057 件)。
スキル自体の 3 つの要素が暴走を防ぎます:
- 予算予約のルール。 各ウェーブの前に、親はハンター、検証パス、ウェーブ後の批評者、そして最終のクリーン批評者のための予算を予約しなければなりません。
HUNTING.mdはこう述べています:これらの必須の予約が収まらなければ、そのウェーブからは一切ハンターを起動せず、ユニットを予算理由付きで延期(deferred)としてマークする。延期されたユニットで終わる実行は、壊れた実行ではなく、あなたの予算を尊重した実行です。 - 狭い任務。 すべてのサブエージェントは 1 つのユニットまたは 1 つの候補を受け取ります。Cloudflare のハーネスは各エージェントをコンテキストウィンドウの 25% 未満に保ち、プロンプトの文言よりもそれが発見の品質に寄与したとしています。
- ガイダンスモード。 ほとんどのセキュリティの質問にはパイプラインは不要です。直接尋ねれば、スキルは何も生成せずに答えます。
あなたの側では:初回の実行を 1 つのディレクトリにスコープする;ハンターには大きなコンテキストと安価なキャッシュ読み取りを持つモデルを、検証者にはより強力なモデルを使う;セッションにタスク予算を設定する;そしてセッション制限で打ち切られた実行を失敗ではなく部分的なものとして扱う。台帳がどこで止まったかを正確に記録しているからです。
Semgrep、CodeQL、AI コードレビューとの位置関係
これは静的解析の代替ではなく、そうなろうともしていません。Cloudflare の記事には示唆的な詳細があります:彼らは Semgrep をハーネスに組み込みましたが、エージェントはそれを「完全に無視し」、コードを読んで実行することを好みました。静的ツールは既知のパターンに対する決定論的で安価で反復可能なカバレッジを提供します。このスキルは、パターンマッチャーでは表現できない境界の失敗に対する、高価で確率的で推論の重いカバレッジを、静的ツールにはない検証ステップとともに提供します。両方を実行してください。そして PR 時のレビューと混同しないでください:Alibaba の open-code-review はプルリクエストごとに数秒で実行される差分レビュアーであり、これは静止状態のコードベースに対する数時間の監査です。
理解度チェック
0/6出典と参考資料
- GitHub の cloudflare/security-audit-skill — README、
SKILL.md、フェーズガイド(RECONNAISSANCE.md、HUNTING.md、VALIDATION-AND-REPORTING.md)、AI-AND-LLM.mdを含む 14 の攻撃クラスガイド、report-schema.json、2 つのバリデータ;MIT - 独自の脆弱性ハーネスを構築する — Cloudflare ブログ、2026 年 6 月 18 日(Grant Bourzikas):スキルがフリートハーネスに成長した経緯、20,799 → 12,057 → 7,245 のファネル、3 万行リポジトリあたり 3〜4 時間という数字、「自分の宿題を自分で採点する」ルール、ネストされた Docker と 200 OK にエラーが乗る落とし穴
- Hacker News の議論(item 49736466) — 当事者によるトークン報告とコストへの反発
- vercel-labs/skills —
npx skills addCLI と、各エージェントに対してスキルをインストールする場所 - Agent Skills オープン標準 — 1 つの
SKILL.mdが Claude Code、Codex、Cursor、Gemini CLI で動く理由
次のステップ
- インストールするエージェントスキルの審査 — このスキルはあなたのリポジトリのコードを実行するエージェントを生成します。このスキルを含め、どんなスキルを信頼する前にも読んでください
- 自律実行の堅牢化 — 数時間の無人監査に必要なサンドボックス、シークレット、送信先の設定
- Open Code Review:Alibaba のハイブリッド AI レビュアー — PR 時の対応物であり、同じ精度対再現率の教訓