定義と結論
AI生成コードのリスク確認とは、提案されたコードを採用する前に、APIの実在、version互換性、入出力契約、失敗時、セキュリティ、既存設計、依存、テストを証拠で検証する作業です。コードがAI製か手書きかで品質基準を変えるのではなく、AIが作りやすい「もっともらしい誤り」を意識して確認します。
構文が自然でビルドが通ることと、要件を満たし安全に運用できることは別です。 結論は、小さな差分へ分け、公式資料、型、テスト、実行結果、レビューを組み合わせて、一つずつ採否を決めることです。
なぜ必要か
生成AIは、学習したパターンから自然なコードを作れますが、対象リポジトリの暗黙仕様、最新version、運用データ、権限境界を自動的に保証しません。存在しそうなAPI名、古い設定、成功時だけの処理、過剰な依存追加を提案することがあります。
動作確認を正常系だけで終えると、null、通信失敗、二重送信、権限不足で壊れます。AI生成コードの速さは、検証を省略する理由ではなく、検証可能な小さな単位を増やすために使います。
登場人物と対象
- 依頼者: 目的、制約、変更可能範囲を定義する
- AI: コードや説明を提案するが、採用判断は行わない
- 実装担当者: 差分を理解し、検証結果を残す
- レビュアー: 仕様、設計、セキュリティ、回帰を独立確認する
- CIと実行環境: 静的解析、テスト、ビルド、実動作を検証する
- 利用者・運用者: 失敗時や障害時の影響を受ける
対象は生成されたソースだけではありません。package追加、設定、migration、workflow、shell command、テスト削除、ログ出力も確認対象です。
リスク確認の流れ

1. 目的と差分を固定する
変更理由、成功条件、変更対象、非対象を先に書きます。生成前後のdiffを読み、無関係な整形やファイル変更を分離します。
2. APIとversionを確認する
関数、option、import先が公式資料に存在し、プロジェクトのversionで利用できるかを確認します。型補完やコンパイラは有力な証拠ですが、実行時契約までは保証しません。
3. データと権限境界を追う
入力の出所、validation、認証と認可、出力先、ログを確認します。ユーザーIDを受け取るだけでなく、現在の利用者がその対象を操作できるかを検証します。
4. 失敗条件を列挙する
null、空、上限、timeout、外部API失敗、再送、同時実行、部分成功を考えます。エラーを握りつぶす、詳細を利用者へ露出する、無制限に再試行する処理へ注意します。
5. 既存設計と依存を照合する
既存の型、error処理、component、DB access、test方針を優先します。新規packageは必要性、保守、license、サイズ、脆弱性を確認します。
6. テストしレビューする
正常系、失敗系、境界、権限違いのテストを追加し、lint、型、test、buildを実行します。高リスク領域は別担当が確認します。
比較と主要リスクパターン
| パターン | 見分ける手がかり | 確認方法 |
|---|---|---|
| 存在しないAPI | 自然だが検索・型で見つからない | 公式資料と導入version |
| 古い実装 | 非推奨警告、古い記事の形 | migration guideと設定 |
| 入力検証不足 | 外部入力を直接利用 | schemaと境界テスト |
| 認可漏れ | IDだけで対象を取得・更新 | 別利用者のテスト |
| 例外処理不足 | 成功経路しかない | timeout、null、失敗応答 |
| 過剰実装 | 依頼外の抽象化や依存 | diffと変更目的 |
| 弱いテスト | 実装の内部だけを確認 | 利用者から見た振る舞い |
最も危険なのは、コードが派手に失敗する場合だけでなく、権限を越えて静かに成功する場合です。
具体例: ユーザー情報更新API
AIが userId をrequest bodyから受け取り、そのIDのユーザーを更新するコードを提案したとします。入力schemaとSQLのparameter化が正しくても、ログイン中の利用者がその userId を更新できるか確認していなければ水平権限昇格になります。
修正では、認証済みの主体をsessionなど信頼できる情報から取得し、対象との関係または必要なroleを認可層で確認します。存在しない対象、権限なし、競合時のstatusを既存API契約へ合わせます。別利用者のID、未認証、無効入力、正常更新をテストします。
また、AIが導入を提案したpackageが本当に必要か調べます。標準機能や既存依存で足りるなら追加せず、lockfileの大きな変更も理由なく受け入れません。
よくある誤解
ビルドが通れば正しいわけではありません。型が合っても業務条件、認可、性能、運用上の契約は間違えられます。
AIに自己レビューさせれば独立レビューになるわけでもありません。同じ文脈と前提から同じ見落としを繰り返す可能性があります。
生成箇所だけ読めばよいとも限りません。呼び出し元、設定、DB schema、古いデータ、公開APIの利用者へ影響します。
注意点とベストプラクティス
- 生成前に目的、非目的、変更ファイルを指定する
- 一度に一つの振る舞いだけを実装する
- 公式資料を対象versionへ合わせて確認する
- 認証と認可を別の確認項目にする
- SQL、HTML、shellなど出力先に応じた安全なAPIを使う
- secret、token、個人情報をコードやログへ入れない
- test削除や検証無効化を安易に受け入れない
- 理解できないコードは採用せず、説明可能な形へ小さくする
AIの説明は根拠の候補であり、公式資料や実行結果そのものではありません。
デバッグと確認方法
ケーススタディ: ファイルアップロード処理のレビュー
AIが生成した画像アップロードAPIが正常系テストを通ったとします。悪いレビューは、拡張子が画像であることと保存成功だけを確認するものです。利用者が指定したファイル名をそのままパスへ連結する、宣言されたMIME typeだけを信じる、容量上限がない、公開領域へ即保存する実装なら、正常に動くほど危険な入口になります。
確認は資産、入力、境界、失敗時の順で行います。守る資産はサーバー上の既存ファイル、保存容量、他利用者の画像です。入力はファイル名、実体、サイズ、個数で、境界は認証、保存先、画像処理ライブラリです。良い例は、サーバー側で名前を採番し、実体を検査し、容量と個数を制限し、非公開領域で処理してから公開し、失敗時に一時ファイルを消します。悪い例は、危険な一行だけを直し、タイムアウト時の残骸や他人のファイル参照を確認しない修正です。
テストでは二重拡張子、空ファイル、巨大画像、壊れた画像、同名同時送信、権限のない参照、画像処理失敗を試します。観測対象は拒否率だけでなく、処理時間、保存容量、一時ファイル数、失敗応答に内部パスが出ていないかです。生成コードの採用判断は「脆弱性らしい文字列がない」ではなく、信頼境界を越える各入力に制限があり、その制限がテストと運用メトリクスで確認できるかによって行います。
まずdiffを目的と照合し、変更されたファイル、依存、設定を一覧にします。API名とoptionを公式資料で確認し、プロジェクトのversionを照合します。次に外部入力から保存・表示・ログまでデータの流れを追い、認可の判断地点を探します。
テストは修正前に問題を再現できる形が理想です。正常系だけでなく、空値、上限、別利用者、再送、依存先失敗を選びます。lint、型、test、buildの結果を残し、実画面やAPIも確認します。再現できない指摘は即修正せず、追加調査が必要な仮説として扱います。
まとめ
AI生成コードは、自然な見た目を信頼の根拠にしません。API実在性、version、入力、認可、失敗、依存、既存設計、テストを小さな差分ごとに確認します。AIは候補を作り、人間と自動検証が採否を決めます。説明でき、再現でき、戻せる状態になって初めて完了です。
参考リソース
- OWASP Top 10 for LLM Applications
- NIST Secure Software Development Framework
- GitHub Docs: Responsible use of GitHub Copilot code review