第7回 AI生成コードのレビュー観点 — 何を見て、AIに何をレビューさせるか
AI生成コードのレビューを「機械が確実にやる層・AIにやらせる層・人間が必ず見る層」に分け、OWASP Top 10:2025 と ASVS 5.0.0 を土台にした観点リストと、そのまま使えるレビュー依頼テンプレートをまとめます。
この回のキーメッセージ
「動くコード」と「安全なコード」は別物です。レビュー観点を決めずにAIへ「セキュリティレビューして」と頼んでも、目立つ指摘が数件返ってくるだけで終わります。
ここまでの6回は、AIエージェント側の設定でリスクを下げる話でした。今回からは対象が変わり、エージェントが書き上げたコードそのものを見ます。権限をどれだけ絞っても、生成されたコードに認可漏れがあれば本番で事故になります。
この回は第8回(認証・認可の各論)と第9回(入出力と外部連携の各論)の総論です。個別の観点は次の2本に譲り、ここでは「どの観点リストを土台にするか」「何を機械に、AIに、人間に割り当てるか」「AIに頼むときどう書くか」を扱います。運用設計(誰がいつ実行するか、指摘の出力契約、偽陽性の測定)は AIコードレビュー導入と運用 にあるので、ここでは運用の器ではなく、中身に入れる観点そのものを書きます。
1. AI生成コードのどこが弱いのか
AIは「テストが通る実装」を書くのが得意です。問題は、セキュリティ要件の多くがテストに現れない前提として存在していることです。
「注文詳細を取得するAPI」を実装させると、注文IDで検索して返すコードが出てきます。テストは通ります。しかし「この注文を見てよいのは誰か」という前提はコードにもテストにも書かれないため、他人の注文IDで他人の注文が返る実装でも、テストは何も教えてくれません。落ちやすいのはこの種の「明示されていない前提」で、誰がこのデータを見てよいか、どこまで信頼してよい入力か、失敗時にどう振る舞うべきか、その値をログへ残してよいか、といった判断がまとめて抜けます。
秘密情報については定量的なデータがあります。GitGuardian の「State of Secrets Sprawl 2026」によれば、Claude Code の支援で書かれたコミットのハードコード秘密の混入率は 3.2%、全体のベースラインは 1.5% でした。資格情報を露出させる確率がおよそ2倍ということです。
AIが「危険なコードを書く」というより、人間なら書いたあとに一瞬考える確認を飛ばすという性質です。人間も同じミスをしますが、生成の速度と量が違うため、同じ確率でも絶対数が増えます。
2. 既製のチェックリストを土台にする
観点をゼロから作る必要はありません。業界標準のリストを土台にし、自分のプロジェクトに関係する部分だけを残すのが最短です。
OWASP Top 10:2025
Web アプリのリスク分類として最も広く使われているリストで、現行版は 2025 版です。2021年版以来のメジャー改訂として2025年11月に発表され、2026年1月に確定しました。
| カテゴリ | AI生成コードで特に出やすいか |
|---|---|
| A01:2025 Broken Access Control | 非常に出やすい。仕様に書かれない限り所有者チェックが入らない |
| A02:2025 Security Misconfiguration | 出やすい。CORS 全許可、デバッグ設定の残存など、動作優先の設定が残る |
| A03:2025 Software Supply Chain Failures | 出やすい。存在確認の甘いパッケージ追加、バージョン固定なしの依存 |
| A04:2025 Cryptographic Failures | 中程度。既製ライブラリを選ぶ傾向はあるが、設定値は雑になりやすい |
| A05:2025 Injection | 中程度。ORM 経由なら安全側に寄るが、動的クエリを頼むと崩れる |
| A06:2025 Insecure Design | 出やすい。指示された機能だけを作り、設計上の脅威を問い返さない |
| A07:2025 Authentication Failures | 中程度。ライブラリ任せの部分は堅いが、レート制限や失効処理が抜ける |
| A08:2025 Software or Data Integrity Failures | 中程度。ビルド成果物や更新経路の検証を自発的には作らない |
| A09:2025 Security Logging & Alerting Failures | 出やすい。ログは書くが「何を残し、何を残さないか」の判断がない |
| A10:2025 Mishandling of Exceptional Conditions | 非常に出やすい。安全側へ倒す設計がなく、握りつぶしや既定値返却になる |
2025 版で特に押さえておきたい変更は3点です。
- A03 Software Supply Chain Failures の新設。旧版の「Vulnerable and Outdated Components」を拡張し、依存の取得経路やビルドの完全性まで含みます。AIに依存追加を任せると、パッケージ名の妥当性を確認しないまま
package.jsonに行が増えるため直接効きます。 - A10 Mishandling of Exceptional Conditions の新設。例外・想定外入力への振る舞いが独立カテゴリになりました。AI生成コードでは、正常系より先に「失敗したときどうなるか」を見る価値があります。
- A02 Security Misconfiguration が5位から2位へ上昇。コードより設定側の事故が増えているという評価で、第10回のデプロイ基盤チェックと直結します。
なお A05 Injection から SSRF が外れ、A01 へ吸収されました。2021年版のままのチェックリストでは、この移動を反映しないと SSRF が抜け落ちます。
OWASP ASVS 5.0.0
Top 10 が「よくあるリスクの分類」なのに対し、ASVS(Application Security Verification Standard)は「検証すべき要件のカタログ」です。最新の安定版は 5.0.0(2025年5月30日公開)で、17章構成・3レベルからなり、PCI DSS 4.0.1 や EU CRA とのマッピングが付いています。
使いどころは観点を増やすことではなく、「どこまでやるか」を決めることです。
| レベル | 想定 | 小規模プロダクトでの扱い |
|---|---|---|
| レベル1 | 基礎的な検証 | 個人開発や社内ツールの最低ライン。全項目満たす前提で設計する |
| レベル2 | 標準的なアプリケーション | 顧客データや決済を扱うならこの水準を目標にする |
| レベル3 | 高い保証が必要なもの | 医療・金融・重要インフラ。通常は最初から狙う必要はない |
項目一覧は公式リポジトリで公開されているので、該当章を直接参照してください。項番はバージョンで動くため、この記事へ引き写すことはしません。現実的な使い方は「全項目を毎回見る」ではなく、開始時に目標レベルを1つ決め、その章から関係する項目だけを抜き出して固定のレビュー観点にすることです。抜き出した観点は AGENTS.md やレビュー用プロンプトへ置き、毎回同じものを使います。
OWASP Top 10 for LLM Applications 2025
ここまでの2つは、アプリが LLM を使うかに関係なく適用されます。OWASP Top 10 for LLM Applications 2025 は、アプリ自体が LLM を組み込む場合に追加で見るリストです。
- LLM01 Prompt Injection(2回連続で1位)
- LLM02 Sensitive Information Disclosure(6位から2位へ上昇)
- LLM03 Supply Chain
- LLM04 Data and Model Poisoning
- LLM05 Improper Output Handling
- LLM06 Excessive Agency
- LLM07 System Prompt Leakage(新設)
- LLM08 Vector and Embedding Weaknesses(新設)
- LLM09 Misinformation
- LLM10 Unbounded Consumption(新設)
AIエージェントを組み込んだアプリで実務上いちばん効くのは LLM05 Improper Output Handling と LLM06 Excessive Agency です。
LLM05 は、モデルの出力を検証せず下流へ渡すことです。返ってきた文字列をそのまま HTML として描画する、生成された SQL をそのまま実行する、といった実装が該当します。原則はモデルの出力を外部入力と同じ扱いにすることです。
LLM06 は、エージェントに与えたツールや権限が必要以上に広いことです。読み取りで足りる処理に書き込み権限のキーを渡す、削除系 API まで公開する、といった設計が該当します。第2回・第3回のエージェント権限設計を、自分が作るアプリのエージェント部分にも適用するということです。
3. レビューの3層 — 何を誰に割り当てるか
観点が揃っても、全部を人間が毎回見るのは続きません。実務では観点を3つの層に割り当てます。
| 層 | 割り当てる観点 | 手段 |
|---|---|---|
| 機械が確実にやる層 | 判定が決定論的で、人が見ても結論が変わらないもの | lint、型検査、シークレットスキャン、SCA、フォーマッタ |
| AIにやらせる層 | 判定に文脈が要るが、観点を与えれば網羅的に見られるもの | 観点を明示したレビュー依頼、差分への一貫したチェック |
| 人間が必ず見る層 | 事業判断・設計意図・影響範囲の見積もりが要るもの | 認可の設計、データの見せてよい範囲、事故ったときの影響範囲 |
原則は、下の層でできることを上の層へ持ち上げないことです。lint で捕まる問題をAIに探させるのは時間と費用の無駄で、AIの注意力も細かい指摘に浪費されます。
3層はどれを省いても表面上は回ります。問題は、漏れるものが層ごとに違うことです。
| 省いた層 | 漏れるもの |
|---|---|
| 機械の層 | ハードコードされた秘密、既知の脆弱性を持つ依存、型の不整合。AIも人間も見落とす類のものが本番へ行く |
| AIの層 | 差分全体にわたる一貫したチェック。人間は後半ほど注意力が落ちるため、大きなPRの終盤に入った問題が抜ける |
| 人間の層 | 「この設計でよいのか」という判断。個々のコードは正しいが、見せてはいけないデータを見せている類の事故 |
人間の層はAIで代替できません。AIは「この関数に認可チェックがない」は指摘できますが、「このデータを同じ組織の別部署に見せてよいか」は判断できません。それは仕様であって、コードから読めないからです。逆に機械の層を人間で代替すべきでもありません。目視確認では 3.2% の混入率に勝てません。
CI 側での実装(どのチェックをいつ走らせ、何をマージブロックにするか)は CI/CDガードレール構築 にワークフロー例があります。
4. AIにレビューを依頼するプロンプトの設計
3層のうち、AIの層をどう回すかが実務ではいちばん差が出ます。
「セキュリティレビューして」が効かない理由
観点を指定せずに依頼すると、モデルは「セキュリティ」という広い空間から目立つものを拾って返します。SQL インジェクションや XSS は挙がりますが、認可漏れや例外時のフォールバックのようなコードの文脈を読まないと分からない問題は、指摘されないまま「特に重大な問題は見つかりませんでした」で終わります。観点は無限にあるので、絞らなければ探索も絞られません。良いレビュー依頼とは、探索空間を狭めることそのものです。
効くプロンプトの4条件
| 条件 | 理由 |
|---|---|
| 対象範囲を絞る | 差分のファイル・関数を明示する。全体を投げると、変更していない部分の一般論が返る |
| 観点を明示的に列挙する | 「A01 の観点で」ではなく「呼び出し元で所有者チェックがあるか確認する」まで具体化する |
| 「問題なし」を許さず根拠を書かせる | 該当なしなら「なぜ該当しないか」を1行書かせる。書けない観点は確認されていない |
| 深刻度と再現条件を書かせる | 再現条件を書けない指摘はたいてい推測。優先順位付けにも使える |
3つ目が特に効きます。「問題があれば教えて」だとモデルは沈黙をコストゼロで選べますが、観点ごとに何か書かせると、確認されていない観点が可視化されます。
レビュー依頼テンプレート
観点リスト部分を差し替えて使う形にしてあります。中身は第8回・第9回で埋めます。
以下の差分をセキュリティ観点でレビューしてください。
## 対象
- ブランチ: feat/order-detail-api
- 差分: `git diff main...HEAD -- src/api/orders/`
- 変更の意図: 注文詳細の取得APIを追加する
## 前提(コードから読めない情報)
- 認証は middleware で済んでおり、`ctx.user` に認証済みユーザーが入る
- 注文は組織単位で分離されており、他組織の注文は一切見えてはならない
- このAPIはブラウザから直接呼ばれる(サーバー間通信ではない)
## 確認してほしい観点
1. 認可: 副作用や返却の前に、リソース所有者の確認があるか
2. 認可: ID の推測でほかのリソースへ到達できないか
3. 入力: 外部から来る値を境界で検証しているか(型・範囲・列挙)
4. 出力: レスポンスに必要以上のフィールドが含まれていないか
5. 例外: 失敗時に安全側へ倒れるか。catch で既定値を返していないか
6. ログ: トークン・個人情報・リクエストボディを出力していないか
7. 設定: CORS・キャッシュ・認証ヘッダの扱いに緩い設定がないか
## 出力の形式
観点ごとに、以下を必ず書いてください。該当なしの観点も飛ばさず、
「なぜ該当しないと判断したか」を1行で書いてください。
- 観点番号
- 判定(問題あり / 問題なし / 判断不能)
- 根拠(該当するファイルと行。判断不能ならその理由)
- 深刻度(high / medium / low)
- 再現条件(どんなリクエストで問題が起きるか)
- 最小の修正案
推測で断定しないでください。差分の外を確認しないと判断できない場合は
「判断不能」とし、確認すべきファイルを挙げてください。
要は「前提」の節です。認可の正解はコードから読めないため、ここを書かないとAIは「認証済みなら見てよい」と仮定します。この節を書く作業自体が、人間がやるべき設計確認になっています。
AIレビューの限界
- リポジトリ全体の文脈を持ちません。 差分の外で認可が済んでいるか、この関数がどこから呼ばれるかは、渡していなければ知りません。「判断不能」を許す出力形式にしているのはそのためです。
- 認可の「意図」を知りません。 誰が何を見てよいかは仕様で、コードから逆算できるのは実装された挙動だけです。実装が間違っていても、一貫していれば正しく見えます。
- 同じ指摘を繰り返します。 却下した指摘は観点リストから外すか、前提の節に「この点は意図的にこうしている」と書いて渡します。
- 深刻度の見積もりが安定しません。 並べ替えの手掛かりに留め、対応期限の根拠にはしない方が安全です。
AIレビューは人間レビューの置き換えではなく、人間が見るべき箇所へ注意を集めるフィルタとして置くのが実態に合っています。
5. 各論はこの先の回で
この回で決めたのは、土台にするリスト、3層の割り当て、AIへの依頼の形です。「確認してほしい観点」に何を書くかは、この先の3回で埋めます。
| 回 | 扱う範囲 |
|---|---|
| 第8回 認証・認可のレビュー各論 | A01 と A07。認証と認可の分離、所有者チェックの置き場所、宣言的な認可の検証方法 |
| 第9回 入出力と外部連携のレビュー各論 | A05 と LLM05。境界での入力検証、レスポンスに載せてよい範囲、外部APIとモデル出力の扱い |
| 第11回 秘密情報とサプライチェーン | A03 と A08。秘密の混入検知、依存追加のレビュー、npm エコシステムの事例から得た対策 |
設定側の確認(A02)は、コードレビューではなくデプロイ直前のチェックとして 第10回 デプロイ基盤の本番前チェック で扱います。
まとめ
- AIは「テストが通る実装」を書くのが得意で、テストに現れない前提を落とします。Claude Code 支援コミットの秘密混入率 3.2% に対し、ベースラインは 1.5% という調査結果があります。
- 観点はゼロから作らず OWASP Top 10:2025 を土台にします。新設の A03・A10 と、順位を上げた A02 が AI生成コードで特に効きます。
- ASVS 5.0.0 は「どこまでやるか」を決める道具です。目標レベルを1つ決め、該当章から固定の観点を抜き出します。アプリ自体が LLM を使うなら LLM05 と LLM06 を追加で見ます。
- 3層のうち機械を省くと秘密と既知脆弱性が素通りし、AIを省くと大きなPRの終盤が抜け、人間を省くと「見せてはいけないデータ」の事故が残ります。
- AIへの依頼は、対象を絞り、観点を列挙し、該当なしにも根拠を書かせ、深刻度と再現条件を求めます。「前提」を書く作業自体が人間側の設計確認になります。
参考リンク
- OWASP Top 10:2025 Introduction — 現行版のカテゴリ一覧と改訂の背景
- OWASP Application Security Verification Standard — ASVS のプロジェクトページ
- OWASP ASVS リポジトリ — 5.0.0 の全項目と各言語版
- OWASP Top 10 for LLM Applications 2025 — LLM を組み込むアプリ向けの追加リスト
- AI-Generated Code Security(Cloud Security Alliance) — AI生成コードのセキュリティ課題に関する調査ノート