
AI生成コードのセキュリティ確認|見落としやすい穴の型
AIに書いてもらったコードが、ちゃんと動いた。テストも通った。 ほっとして、そのままコミットしようとした手が、ふと止まる——「これ、動くのはわかったけど、セキュリティ的に大丈夫なんだっけ」。
APIキーがそのまま書かれていないか。ユーザーの入力をそのままクエリに入れていないか。出力をエスケープせずに画面へ返していないか。AIが生成したコードは「動く」ことは得意でも、「安全である」ことは保証してくれません。動作確認では緑になるのに、セキュリティの穴だけは静かにそこに残る——このすれ違いは、AIコーディングでいちばん見落とされやすい場所のひとつです。
「AIを使え」と急かされている現場ほど、スピードは出るけれど、この一段だけ確認が飛ばされがちです。でも大丈夫。セキュリティのすべてを毎回見張る必要はありません。穴が空きやすい場所は、だいたい決まっています。まずそこだけ立ち止まれるようになれば、大きな踏み外しの多くは防げます。今日は、その「見るべき場所」を一緒に整理していきましょう。
結論:AI生成コードのセキュリティは、穴が空きやすい3カ所を先に見ると効率よく確認できます。①入力と出力の境界(外から来た値をそのままクエリ・コマンド・画面に流していないか=インジェクション/XSS)/②秘密と権限(APIキーやパスワードのべた書き、認可チェック漏れがないか)/③依存とデフォルト(AIが提案したライブラリが実在し安全か、verify=False やワイルドカード許可のような危険な初期設定が混ざっていないか)。明日からできるのは、(1) 外部入力がクエリ・コマンド・HTMLに直接つながる箇所を探して、パラメータ化・エスケープされているか見る → (2) 秘密情報のべた書きと、権限チェックの有無を確認する → (3) 追加されたライブラリと危険なデフォルト設定を洗うの3つ。末尾にレビュー用プロンプトとチェックリストを置きました。なお本記事は一般的な実務情報です。重要なシステムでは、必ず自社のセキュリティ担当や専用ツールの確認も併用してください。
セキュリティの確認は、AIを疑って足を止めるためではありません。 「これは安心して本番に出せるコードだ」と自分で言えるようにするための、最後のひと手間です。
なぜAIのコードは「動くのに危ない」ことがあるのか
AIは、大量のコードを学習して「よくある書き方」を再現します。だから多くの場合、それらしく動くコードが返ってきます。ただ、学習元には急ぎで書かれた例やセキュリティが甘い例も混ざっていて、AIは「動く書き方」と「安全な書き方」を必ずしも区別しません。
しかも、セキュリティの穴は動作確認ではまず見えないのが厄介なところです。
- SQLインジェクションの余地があっても、正常な入力では普通に動く
- APIキーがべた書きでも、機能としては問題なく動く
- 出力をエスケープしていなくても、ふつうの文字なら表示は崩れない
つまり「テストが緑だから安全」ではないのです。安全かどうかは、攻撃者の視点で、わざと変な値を入れたらどうなるかを別に確かめないとわかりません。ここはAIが自動でやってくれない部分で、人が意識して見る必要があります。とはいえ闇雲に全部を疑うと疲れてしまうので、次の3カ所に的を絞ります。
穴が空きやすい3カ所を先に見る

セキュリティの穴は無数にあるように感じますが、AI生成コードで実際によく出るものは、大きく3カ所にまとまります。この順で見ると、少ない手間で効きます。
- ①入力と出力の境界:外から来た値(ユーザー入力、URL、ファイル、外部API)が、そのままクエリ・コマンド・HTMLに流れていないか。ここがインジェクションやXSSの入口です。
- ②秘密と権限:APIキー・パスワード・トークンがコードに直接書かれていないか。そして「この人がこの操作をしてよいか」の認可チェックが抜けていないか。
- ③依存とデフォルト:AIが追加したライブラリが実在し、メンテされているか。そして
verify=Falseや全許可のような危険な初期設定が紛れ込んでいないか。
3つとも、AIが「動くコード」を作るときに素通りしやすい場所です。次から一つずつ、具体的に何を見るかを見ていきます。
①入力と出力の境界を見る
いちばん被害が大きくなりやすいのが、外から来た値の扱いです。AIは「まず動く形」を優先するため、入力を検証せずそのまま使うコードを返しがちです。
- SQL・クエリの組み立て:ユーザー入力を文字列連結でクエリに埋め込んでいないか。
"... WHERE id = " + userInputのような形は危険信号。プレースホルダ(パラメータ化クエリ)やORMを使っているかを確認します。 - コマンド・シェルの実行:入力値を使って外部コマンドを組み立てていないか。ここもインジェクションの温床です。可能なら入力をコマンドに渡さない設計に。
- 画面への出力(XSS):ユーザー由来の文字列を、エスケープせずにHTMLへ差し込んでいないか。テンプレートエンジンの自動エスケープが効いているかを確認します。
- ファイル・パスの扱い:入力からファイルパスを組み立てて、
../のような値で想定外の場所を読み書きできてしまわないか(パストラバーサル)。 - 入力の検証:そもそも「受け取ってよい値の範囲」をチェックしているか。長さ・型・形式のバリデーションが抜けていないか。
見るコツはシンプルです。「外から来た値」を目でたどり、それがクエリ・コマンド・HTML・ファイルパスに触れる瞬間に、加工(パラメータ化・エスケープ・検証)が挟まっているかを確認する。ここだけでも、大きな穴の多くは見つかります。
②秘密と権限を見る

次に、秘密情報と権限まわりです。ここは「うっかり」で起きやすく、しかも漏れると影響が大きい場所です。
- 秘密のべた書き:APIキー・パスワード・トークン・接続文字列が、ソースコードに直接書かれていないか。AIはサンプルとして平気で埋め込んでくることがあります。環境変数や秘密管理の仕組みに外せているか確認します。
- リポジトリへの混入:秘密がコミットに含まれていないか。
.envなどが誤って追跡対象になっていないかも見ます。一度push した秘密は履歴に残るので、混入を見つけたら鍵の無効化・再発行まで考えます。 - 認可(権限)チェック:ログインしているか(認証)だけでなく、その人がこの操作・このデータにアクセスしてよいか(認可)を確かめているか。AIは正常系を作るのが得意な分、「他人のIDを指定したら他人のデータが見えてしまう」といった権限チェック漏れを残しがちです。
- エラー・ログの情報漏れ:例外メッセージやスタックトレースを、そのまま利用者に返していないか。内部構造や秘密がログ・画面に出ていないか。
ポイントは、「鍵がむき出しになっていないか」と「その操作をしてよい人か確かめているか」の2点を、機能の正しさとは別に必ず一度見ることです。動作確認では素通りしてしまう部分だからこそ、意識して目を向けます。
③依存とデフォルトを見る
3つ目は、AIが追加した「材料」と「初期設定」です。地味ですが、ここも穴になりやすい場所です。
- 提案されたライブラリが実在するか:AIは、もっともらしいのに実在しないパッケージ名を提案することがあります。存在しない名前を狙って悪意ある偽パッケージが登録される手口も知られているので、
importや依存に追加する前に、公式のパッケージ名・配布元を一次情報で確認します。この「もっともらしい嘘」の見抜き方はAIのハルシネーションの見抜き方でも扱っています。 - ライブラリが古い・放置されていないか:提案されたバージョンが古く、既知の脆弱性が残っていないか。メンテナンスが止まっていないか。可能なら
npm audit・pip-auditのような依存の脆弱性チェックを通します。 - 危険なデフォルト設定:
verify=False(証明書検証の無効化)、CORSの全許可(*)、デバッグモードのまま、権限を広く開けた設定など。AIは「まず動かす」ためにこうした緩い設定を入れがちです。本番前に必ず締め直します。 - 暗号・ハッシュの選び方:古い方式(例:パスワードの単純なMD5化)や、自前の暗号実装になっていないか。実績のある標準的な方法に寄せます。
依存とデフォルトは、機能そのものには見えないので後回しにされがちです。でも、追加されたライブラリの一覧と、初期値・設定まわりをさっと一度洗うだけで、見つかる穴は少なくありません。
場面ごとに、かける手間を変える
3カ所すべてを毎回フルで見るのは続きません。扱うものの重さで手間を変えるのが現実的です。
| 場面 | リスク | かける手間 |
|---|---|---|
| 個人の実験・使い捨てスクリプト | 低 | 秘密のべた書きだけ確認すればOK |
| 社内ツール・限定利用 | 中 | ①入出力の境界+②秘密と権限を確認 |
| 外部公開・ユーザー入力を受ける | 高 | 3カ所すべて+依存の脆弱性チェックを実行 |
| 個人情報・決済・認証に触れる | 高 | 自己判断せず、セキュリティ担当・専用ツールも併用 |
大事なのは、全部を最高レベルで疑わないことです。すべてに全力を出そうとすると確認が形骸化して、本当にこわい所を見逃します。「外部に公開する・ユーザー入力を受ける・機密や決済に触れる」——このどれかに当てはまるときにだけ、しっかり手をかければ十分です。
こういうときは、特に立ち止まる
以下は、セキュリティの穴が残りやすい「サイン」です。ひとつでも当てはまったら、コミット前にもう一段だけ丁寧に見る合図と考えてください。
- ユーザー入力を受け取って、DB・コマンド・画面に流している:パラメータ化・エスケープ・検証が挟まっているか。
- コード内に文字列の鍵・パスワードらしきものが見える:環境変数・秘密管理へ外し、混入していれば鍵を再発行。
- 見慣れないライブラリが追加されている:名前が実在し、メンテされ、脆弱性がないか一次情報で確認。
- **
verify=Falseや*、デバッグ有効のような緩い設定がある**:本番前に締め直す。 - 認証はあるが「誰がどのデータを見てよいか」の確認が見当たらない:認可チェックの抜けを疑う。
これらは「危険だから怖がれ」という合図ではありません。どこで一段だけ丁寧に見ればいいかの目印です。目印を知っていれば、それ以外の場所では安心してスピードを出せます。
ありがちな落とし穴と、その回避
- 「テストが通ったから安全」と考える:機能テストは正常系を見るもの。セキュリティは、わざと変な値を入れて別に確かめる。
- AIに「安全ですか?」とだけ聞いて信じる:AIは自分の出力を過信しがち。観点を具体的に指定して洗わせ、最後は人が確認する。
- 秘密のべた書きを「あとで直す」と放置する:あとでが来ないまま push されがち。見つけたその場で外す。
- 提案されたライブラリを名前だけで入れる:実在・メンテ・脆弱性を確認せず追加しない。
- 緩いデフォルト設定のまま本番へ:
verify=Falseやデバッグ有効は、動作確認では気づかない。設定を一度洗う。
落とし穴の多くは、「動いたから大丈夫だろう」で確認を飛ばすことから来ます。 でも、見るべきなのは毎回すべてではありません。入出力の境界・秘密と権限・依存とデフォルト——この3カ所。そこにだけ目を向ければ、負担を増やさずにリスクは大きく減らせます。
明日からやること(小さく始める3つ)
一度に全部を仕組み化しようとすると続きません。まずこの3つから。
- 外部入力がクエリ・コマンド・HTMLに触れる箇所を探し、加工が挟まっているか見る:パラメータ化・エスケープ・検証のどれかが入っているか。ここがいちばん被害が大きい場所です。
- 秘密のべた書きと、権限チェックの有無を確認する:鍵がむき出しになっていないか、その操作をしてよい人か確かめているか。
- 追加されたライブラリと、緩いデフォルト設定を洗う:名前は実在するか、
verify=Falseや全許可が紛れていないか。可能なら依存の脆弱性チェックを一度実行。
この3つだけでも、「なんとなく不安」が「どこを見ればいいか分かっている」に変わります。 慣れてきたら、依存の脆弱性チェックをCIに組み込んだり、チームで観点を共有したりと、少しずつ広げていけば十分です。
コピーして使う「AI生成コード セキュリティ確認プロンプト」
AIにレビューさせる一次チェックとして使うと、観点の抜けが減ります。ただしAIの指摘は当たり外れがあるので、最後は必ず人が確認する前提で。
以下のコードを、セキュリティの観点だけでレビューしてください。
機能の良し悪しではなく、攻撃者の視点で「悪用できる穴」を探してください。
次の3カ所を重点的に見て、該当箇所を行単位で指摘してください。
1. 入力と出力の境界:外部入力がクエリ・コマンド・HTML・ファイルパスに
検証やエスケープなしで流れていないか(インジェクション/XSS/パストラバーサル)
2. 秘密と権限:APIキー・パスワード等のべた書き、認可(権限)チェックの抜け、
エラーやログからの情報漏れがないか
3. 依存とデフォルト:実在しない/古い/脆弱なライブラリ、verify=False や
CORS全許可・デバッグ有効などの危険な初期設定がないか
各指摘には「なぜ危険か」「どう直すか」を短く添えてください。
判断に自信がない箇所は「要人間確認」と明記してください。
--- 対象コード ---
(ここにコードを貼る)
AI生成コード セキュリティチェックリスト
コミット前・公開前に、1項目ずつ「○/要確認/該当なし」を付けながら使ってください。各セクションの ★印は「これだけは外せない最低ライン」。忙しい日は★だけ、残りは余裕のある日に——と読んでください。
①入力と出力の境界
- ★ 外部入力をクエリに使う所で、パラメータ化(プレースホルダ)やORMを使っているか
- ユーザー由来の文字列を、エスケープせずにHTMLへ出していないか
- 入力からコマンド・ファイルパスを組み立てて、想定外の実行・読み書きにならないか
- 受け取る値の長さ・型・形式を検証しているか
②秘密と権限
- ★ APIキー・パスワード・トークンがコードにべた書きされていないか(環境変数等に外せているか)
- ★ 認証だけでなく「その人がこの操作・データにアクセスしてよいか」(認可)を確認しているか
- エラーメッセージ・ログに、内部情報や秘密が出ていないか
③依存とデフォルト
- ★ 追加したライブラリが実在し、メンテされ、既知の脆弱性がないか(一次情報・監査ツールで確認)
- verify=False・CORS全許可・デバッグ有効などの危険なデフォルトが残っていないか
- 暗号・ハッシュに、古い方式や自前実装を使っていないか
共通
- 機能テストとは別に、わざと変な値を入れて挙動を確かめたか
- 判断に迷う所は、セキュリティ担当や専用ツールにも確認したか
最後に
AI生成コードのセキュリティを気にするのは、AIを疑って臆病になるためではありません。 「これは安心して本番に出せるコードです」と、自分の言葉で言えるようにするための、最後のひと手間です。
セキュリティの話は、専門用語も多くて身構えてしまいますよね。でも、現場のエンジニアに求められるのは、セキュリティ専門家になることではありません。穴が空きやすい3カ所を知っていて、そこで一段だけ立ち止まれること。それだけで、あとで冷や汗をかく場面の大半は防げます。
今日できたのが、コードの中の鍵のべた書きをひとつ見つけて外しただけでも、それはもう「動いたからOK」で流さなかった、確かな一歩です。
よければ、こちらも
書いたコードの確認をもう少し体系立てたいなら、AI生成コードのレビュー・検証チェックリストや、AIにレビューさせてもバグが残る——人が見るべき観点、そして最低限の動作確認をそろえる生成コードをそのまま使わない動作確認の型とあわせて読むと、AIコードの「こわさ」を一つずつ減らしていけます。

すべてを一度に完璧にする必要はありません。 穴が空きやすい所を一つ、今日ちゃんと確認できたなら、それで十分です。明日また一つ、落ち着いて積んでいきましょう。