security-audit-skill入門:AIの脆弱性候補を、根拠と確認状態で整理する

AIに「脆弱性を探して」と頼んだら、気になる指摘が何件も返ってきた。でも、ほんまに他人のデータを読めるんか、前段の認可処理で止まるんかが分からへん。この状態やと、指摘が増えるほど確認の仕事も増えてしまうで。

Cloudflareのsecurity-audit-skillは、コードを調べるAIに監査の手順と記録の形式を与えるスキルや。期待できる価値は、怪しい箇所の一覧を、修正する・追加確認する・今回は棄却するという判断につなげやすくすることやで。脆弱性を直す製品でも、導入すれば安全になる保証でもない。

この記事では、通常のAIレビューとの違いを、架空の請求書アプリで説明するで。今回、自作の小さな関数の動作と、公式の記録検証処理の一部を実行した。ただし、AIにスキルを使わせた監査全体の実行や、検出率・誤検知率・費用の比較はしてへん。説明例、部分的な実測、公式仕様を分けて読むと判断しやすいで。

普通のAIレビューと、何が違うん?

「この関数に認可チェックがない」という指摘だけでは、アプリ全体の欠陥かどうかは分からへん。呼び出す前にチェックしてるかもしれんし、外部から呼べない内部処理かもしれんからや。

進め方の比較。通常のAIでも詳しく指示すれば同様の調査はできる。スキル導入だけで結果が保証されるわけやないで。
見るところ単発で「脆弱性を探して」と頼む例このスキルの方針
指摘の根拠怪しい関数や行を挙げる入力から処理・保護対象までの経路と、途中の防御も調べる
指摘の再確認見つけたAIの説明をそのまま採用しがち別の検証役へ渡し、指摘を否定できないか確かめる
分からない点注意書きの中に埋もれることがある未確認の事実と、次に何を確認するかを記録する
調査の残り報告に出てこない場所は、調べたか不明調査範囲の台帳で、確認内容と未完了部分を追う

増やしたいのは指摘の件数より、指摘を読んだ人が次の行動を決められる情報や。根拠が足りへんまま修正して正常機能を壊すことや、同じ疑いを次回また最初から調べる手間を減らす狙いがある。これは設計上の狙いで、本記事で削減時間を測ったわけやないで。

請求書の例で、修正判断を比べる

以下はこの記事独自の架空例や。実在サービスやCloudflare製品の脆弱性ではない。要件は「Aliceの請求書はAliceだけが読める」。ところが、次の関数は利用者名を受け取るだけで確認してへん。

const invoice = { id: 'demo-1', ownerId: 'alice', amount: 100 };
function readInvoiceWithoutCheck(userId) {
  return invoice;
}
function readInvoiceWithCheck(userId) {
  return invoice.ownerId === userId ? invoice : null;
}

同じ「この関数に所有者チェックがない」という候補でも、周りを調べると結論は変わるで。

確認できたこと判断の例次にすること
外部の利用者から該当処理へ到達でき、防御がなく、隔離したローカル環境で他人の架空データが返ることまで独立に確認できたconfirmedの候補になる示せた影響に合わせて優先度を決め、適切な認可を実装する
関数のチェック不足は読めるが、呼び出し元や実際の権限設定が手元にないneeds_validationどの経路から呼ばれ、前段で所有者を確認するかを管理者と確認する
候補の経路では、前段の所有者チェックによって他人の請求書へのアクセスが拒否されることが分かったその経路の認可欠如という主張はrejected反証の場所を記録する。別経路まで安全と一般化しない

この区別ができると、「全部直す」でも「AIの誤検知やろと全部放置する」でもなく、対応を分けられる。たとえば未検証なら、修正チケットを急いで作る前に「呼び出し元の所有者確認を見せてほしい」と、具体的な確認依頼を出せるんや。

この記事で実際に確かめた範囲

上の関数に、架空の利用者名だけを渡す4つの検査をNode.js 24.20.0で実行した。ネットワーク通信も実データも使ってへん。

  • チェックなしの関数へBobを渡すと、Aliceの請求書が返る。
  • 所有者を確認する関数へBobを渡すと、nullが返る。
  • 同じ関数へAliceを渡すと、金額100の請求書が返る。
  • 利用者名がない場合も、nullが返る。

4件とも想定どおりやった。ただし、これは所有者を確認する意味を示す、関数単体の実験や。HTTP経路、ログイン、セッション、DBなどは含まない。security-audit-skillが自動発見した実績でも、アプリ全体をconfirmedと判定する根拠でもないで。実際のアプリでは、この条件式を貼るだけで済ませず、サーバーが信頼できる認証情報と対象の所有権を結び付ける必要がある。

持ち帰れる成果物は何なん?

ファイルの数よりも、それを使って誰が何を判断できるかを見るとええで。公式READMEは調査、探索、候補検証、構造化、独立した記録確認、レポート化の流れを説明してる。

成果物中身使いどころ
architecture.md構成と信頼境界利用者入力を、どこから信用してはいけないか共有する
coverage-ledger.json調査単位、確認した箇所、候補、未完了の記録「指摘ゼロ」と「未調査」を混同せず、次の確認先を決める
findings.json根拠と判定を、決まった項目で保存担当者へ引き継ぎ、同じ原因を追跡する
REPORT.mdなど確認済みの内容と未検証事項を、人が読める形に整理修正担当者と追加調査担当者の作業を分ける

たとえば「認可処理を調査済み」と書かれていても、何を見たかがなければ安心材料にはならへん。台帳で対象箇所、調べた方法、未確認部分まで追えることが大事なんや。前回の記録も、コード変更後に古い根拠のまま使い回してええわけではないで。

最後に、どんな出力が残るん?

ここまでの説明だけでは「結局、何が手元に残るん?」が分かりにくかったな。ここでは、ファイルを開いたときの姿と、それを読んだ担当者が次にすることを示すで。下のレポートは、読み方を説明するために手で作った模擬出力や。スキルを実行して生成された監査結果ではない。一方、後半の実行ログは、このブログの説明用コードを実際に動かした出力やで。

まず、フォルダーを開くと

audit-output/
├─ architecture.md        構成・信頼境界の説明
├─ coverage-ledger.json   何を調べ、何が残ったか
├─ findings.json          判定ごとの構造化された記録
├─ REPORT.md              全体の報告
├─ FINDINGS-DETAIL.md     確認済み指摘の詳細
└─ NEEDS-VALIDATION.md    追加確認が必要な候補

これは正式なワークフローで扱う代表的なファイルの配置例や。毎回この6ファイルが必ず生成されるという意味ではないし、途中で止まった監査を完成したことにしたらあかんで。最初にREPORT.mdで実施範囲と完了状態を読み、必要な候補の詳細へ進むんや。

REPORT.mdを読むときのイメージ

次は架空の請求書アプリを題材にした模擬レポートの抜粋や。公式の固定テンプレートの転載でも、実在システムの評価でもないで。

# 請求書アプリの監査メモ(説明用)

実施状態:部分的な調査。アプリ全体の監査は未完了。
対象:請求書を返す関数と、提供された呼び出し元のコード。
対象外:本番環境、実際のログイン処理、未提供のルート設定。

確認済みの脆弱性:0件
追加確認が必要な候補:1件
反証された候補:1件

候補 INV-01:請求書の所有者確認が見当たらない
判定:needs_validation
根拠:請求書を返す関数内には、利用者と所有者の比較がない。
未解決:この関数へ到達する前に、所有者確認があるか不明。
次の確認:管理者からルートと認可ミドルウェアの実装を入手する。
重大度:付けない。アプリとしての到達経路と影響が未確定。

候補 INV-02:別の閲覧経路にも所有者確認がない、という指摘
判定:rejected
反証:その経路では、関数を呼ぶ前に所有者を照合している。
扱い:この指摘による修正は求めない。別の経路は別途確認する。

結論:この出力だけで「アプリは安全」とは言えない。
INV-01の呼び出し経路と、対象外の範囲の確認が残っている。

この出力を受け取ったら、INV-01は「認可コードを入手して確かめる仕事」、INV-02は「今回の主張では修正しない仕事」に分けられる。単に「認可に問題あり」とだけ言われる場合と比べ、次の依頼先と確認内容を決めやすくなるんや。confirmedが0件なのは、安全が証明されたからではなく、確認が済んでへん候補が残っているからやで。

findings.jsonでは、未解決事項を項目として残す

次は、前回の改訂で実際に公式の検証関数へ渡した説明用レコードの一部や。表示を短くするため、title・description・trace・evidenceなどを省いてる。この抜粋だけをfindings.jsonとして検証に渡すことはできへんで。

{
  "verdict": "needs_validation",
  "fingerprint": "demo-invoice-ownership",
  "blockers": [
    "Whether an upstream route enforces ownership is not supplied in this illustrative record."
  ],
  "validation_plan": {
    "local": "Inspect the owner-supplied route and middleware in a disposable copy; compare own and foreign synthetic records without contacting any deployed service."
  }
}

blockersは「前段の経路で所有者確認をしているか、資料がなく分からない」。validation_planは「管理者が提供した経路と認可処理を作業コピーで確認し、架空データを使って自分と他人の場合を比べる」という意味や。「要調査」だけで終わらず、何が分かれば判断できるかを残すところがポイントやで。

実際に動かしたコードの出力

前の節の自作関数に4つの検査を付けたプログラムは、次のログを出した。これは本記事で取得した実行結果や。英語のメッセージは検査プログラム自身が出してるもので、AI監査レポートではないで。

CHECK 1: without ownership check, Bob receives Alice invoice
CHECK 2: with ownership check, Bob receives null
CHECK 3: with ownership check, Alice receives amount 100
CHECK 4: missing user receives null
PASS: 4 local assertions; no network; synthetic records only

1行目はチェックのない関数の問題を示し、2〜4行目はチェックを入れた関数の挙動や。修正後に他人を拒否するだけでなく、正しい所有者が読めることも確認してる。このような期待値と観測結果の組があると、修正担当者は何を守るための変更かを理解できるで。ただし、関数の実験だけでアプリの認証まで検証したことにはならへん。

公式の検証関数へ説明用レコードを渡したチェックでは、次の結果になった。

PASS: illustrative needs_validation record accepted
PASS: severity added to needs_validation record rejected
NOTE: format acceptance does not verify security claims

必要項目をそろえた未検証レコードは受理され、そのレコードへ重大度を付けると拒否された、という意味や。最後の行のとおり、形式検査に通ることと、脆弱性が本物であることは別やで。効果として実測できたのはこの形式上の歯止めまでで、スキル全体の検出性能ではない。

状態を分けると、何を防げる?

公式の検証・報告ルールは、発見役と検証役を分け、現在のコードと観測結果を確認するよう求めてる。別のAIが読んだだけで、別の専門家が保証したのと同じにはならへんで。

記録のスキーマでは、confirmedには成立条件・観測結果・対策・重大度などが必要や。一方、needs_validationは根拠のある候補、具体的な未確認事項、検証計画を持ち、重大度は付けへん。rejectedには反証理由を残す。想像だけの候補を、何でも未検証の箱へ入れる使い方ではないで。

記録チェックも、部分的に動かしてみた

公式コミットc1c8a8c1471069fb0e188eeaff69b8e8db6564a8のvalidate-findings.cjsが公開する検証関数へ、自作の説明用レコードを渡した。needs_validationとして必要な項目をそろえた例は受理され、同じ例に重大度の項目を足すと拒否されたで。

ここで確認できた効果は、未検証の記録を確認済みのような書き方へ混ぜにくくする、形式上の歯止めや。コードの根拠が真実か、脆弱性が成立するかまで検証関数が判断したわけではない。今回実行したのはこの関数への入力検査で、監査全体やCLIの全動作を検証したものでもないで。

どんな人なら、導入する意味がある?

  • 向いてる:複数人へ調査を引き継ぐ、定期的に同じコードを監査する、AIの指摘の真偽を調べ直す手間が多いチーム。根拠と未完了範囲を残す価値がある。
  • 小さく始めたい:数十行の関数について一つの疑問を解きたい場合。まずは「入力から保護対象までの経路、防御、未確認事項を説明して」と頼むだけで十分なこともある。
  • 別の道具も必要:既知の依存パッケージ脆弱性、稼働中システムの設定、運用時の権限を継続確認したい場合。依存関係スキャナーや設定点検、適切な実機検証まで置き換えるものやない。

コストも増えるで。調査役と検証役が別に読み、記録を作るから、単発の質問よりトークン・時間・人の確認が必要になり得る。「自動で何%速くなる」「誤検知が何%減る」という比較値は今回測ってへん。Cloudflareの解説に登場する大規模な監査基盤と、この単一リポジトリ用スキルも同じものとして扱わんといてな。

導入後の効果を、自分で判断する方法

  1. 同じコミットと同じ対象範囲で、従来のレビューとスキルを使うレビューを別セッションに分ける。モデル・実行権限・費用上限もそろえる。
  2. 「件数」だけでなく、指摘の根拠を追えるか、人が成立を確認できたか、重複・誤検知の確認にどれだけ手間がかかったかを記録する。
  3. 未検証事項が「設定次第」だけで終わらず、どの設定・経路を誰が確認すれば決着するかまで書かれているかを見る。
  4. 未調査・中断の範囲と費用も含めて比べる。確認済みゼロでも有用な調査はあり得るし、指摘が多くても役立つとは限らへん。

採用の目安は、追加の監査費用より、根拠の確認・引き継ぎ・再調査の負担を減らせるかや。実際に確かめられる指摘と、次の作業が明確な未検証事項が残るなら、導入価値を検討できるで。

今回のゴールと環境

ここからは導入と静的確認の練習手順や。監査全体の効果測定ではないで。対象コードは実行・ビルドせず、必要な条件が足りなければ未完了として記録する。静的に読めただけでconfirmedへ進めへんことを確かめるんや。

確認した範囲:2026年10月24日に公式READMEや導入資料を読み直して、以下の手順を具体化したで。この改訂でアプリのインストールから最終結果までを実機で通したわけやない。成功の目安は、手元で試すときのチェックとして使ってな。

準備

ここではWindows 11 x64とPowerShellで進めるで。スタートで「PowerShell」を検索して開いてな。Node.js公式ダウンロードで24系LTS・Windows・x64のInstaller(.msi)を選び、ダウンロードしたファイルを開いて画面に沿って入れてな。入れ終わったらPowerShellを開き直すんや。

node --version
npm.cmd --version

両方にバージョンが出たら準備OKや。以下ではWindowsのスクリプト実行ポリシーで止まりにくいnpm.cmdとnpx.cmdを使うで。インストール済みなら入れ直す必要はないで。

Git公式のWindows用ページからx64 Setupをダウンロードし、インストーラーの案内に沿って入れてな。PowerShellを開き直し、git --versionでバージョンが出ることを確認するんや。

今回はClaude Codeを使うで。使えるプランやAPIの支払いは別に必要やから、公式の準備・ログイン案内を先に確認してな。PowerShellで次を実行し、インストール後は新しいPowerShellを開いてな。

winget install Anthropic.ClaudeCode

WinGetがないときは、WindowsのMicrosoft Storeで「アプリ インストーラー」を入れるか更新してからやり直してな。次の確認でバージョンが出たら準備OKや。実際にclaudeを起動するんは、下の練習フォルダーを作ってからやで。初回起動は画面の案内でブラウザーにログインし、戻って入力欄が使えることを確かめてな。

claude --version

PowerShell用のコマンドと、Claude Codeの入力欄へ送る文は別やで。「Claude Codeで入力」と書いたブロックをPowerShellへ貼らんようにしてな。AIにファイルを読ませると、その内容が利用するサービスへ送られることがあるで。最初は以下の架空例だけで試そか。

公式の要件には、並行サブエージェントを使えるエージェントと、対象コードを実行する場合のOS側の隔離があるで。Windowsネイティブだけでその隔離ができたとは扱わへん。今回は静的な確認だけを依頼し、実行が必要な候補は未検証で残すで。

使い方

New-Item -ItemType Directory -Force "$env:USERPROFILE\github-practice\security-audit" | Out-Null
Set-Location "$env:USERPROFILE\github-practice\security-audit"
'export const findItem = (items, word) => items.filter(x => x.includes(word));' | Set-Content sample.js -Encoding UTF8
npx.cmd skills add https://github.com/cloudflare/security-audit-skill --skill security-audit

インストーラーでClaude Codeと練習プロジェクトを選び、導入先を確認するで。その後、同じフォルダーでclaudeを起動してな。

Claude Codeで入力:

security-auditで、この練習フォルダーのsample.jsだけを静的に監査して。対象コードは実行・ビルドせず、外部サイトも調べない。OSで強制した隔離環境はまだ用意していない。動作確認が要る候補はneeds_validationとして残し、脆弱性を無理に作らない。結果はaudit-outputフォルダーへ保存して。

成功の目安:調べた範囲と根拠、未検証の点を区別した記録が残ることや。問題が見つからへん場合もあるで。正式な監査を実施できた場合の出力はfindings.json、coverage-ledger.json、REPORT.mdなどや。部分的な静的確認だけで、それらを作成済み・全工程完了とみなさんといてな。出力があれば自分でも開いて内容を確認してな。実行条件が満たせず止まったら、無理に制約を外さずその理由を残すんや。

仕組みとデータの流れ

自分のPCPCの外自作ソース・監査記録監査エージェント利用するAIサービス入力・操作と結果通信・受け取る情報
スキルは監査手順の指示で、OSの隔離環境そのものやないで。今回の対象コードは実行せず、読ませた内容は利用するモデルへ送られ得るで。構成を単純化した独自図解で、製品の画面や実行結果やないで。細かな通信や保存形式は設定で変わる。スマートフォンでは横へスクロールしてな。

トラブルシューティング

困ったこと確認すること
監査が実行を求める今回は静的確認だけや。対象を動かす要件は未充足として止め、未検証に残すで。
confirmedが増えない未検証を無理に確認済みへ変えんといてな。根拠と成立条件を人が読めることを優先するんや。

終了と再開

Claude Codeで/exitを入力して終了するで。レポートは練習フォルダーに残す。実際のシステムへの適用や動的な検証は、許諾と隔離を別に準備してからや。

公式READMEと最新の導入案内も確認してな。配布版や外部サービスの変更で、手順が変わることがあるで。

権限と未検証の範囲

対象の所有者や管理者の許諾を確認し、外部サービスを無断で試験しないでな。監査対象のコードをビルド・実行すること自体にもリスクがあるため、秘密情報を渡さず、資源や通信を制限するで。

レポートが出たことを、安全性の保証とは考えんといてな。どこを調べたか、どこが未検証か、根拠が現行のソースに対応しているかを確認し、重要な問題は再現条件と影響を専門家が判断してな。

公式資料と利用条件

改訂日:2026年10月26日。利用価値の比較、請求書の説明例、部分的な実測、成果物と採否判断を追加したで。導入からAI監査全体までの一連の実行と検出性能の比較は未検証。下のランキング情報は初回掲載時の記録や。

スキル本体はMITライセンスやで。対象コード、利用するモデル、検証ツールの条件は別やで。

確認日:2026年10月24日。掲載対象はHysen Labsの30日間スター純増CSV(2026年9月23日〜10月23日)の上位20件から、過去掲載を除いて選定したで。Hysen Labsが追跡するリポジトリ内の順位であり、GitHub全体を網羅するランキングやないで。集計は期間末と期間初のスター数の差分。データ提供:Hysen Labs(CC BY 4.0)。機能や条件は公式資料に基づく話やけど、実際の動作や生成結果を本記事で検証したものやないで。