AIアシスタントを使ったグループが書いたコードは、使わなかったグループより安全でなかった。それだけなら「なるほど」で済む。問題は次の発見だ——AIを使ったグループほど、自分のコードの安全性に「自信があった」。
この2つの数字の逆転が、バイブコーディングで最も危険なパターンだ。
Stanfordの実験——47人に「安全なコードを書いて」と頼んだ
2023年、Stanfordのセキュリティ研究者Neil Perryらは、「AIアシスタントを使うとユーザーはより安全でないコードを書くか?」という研究をACM CCS(Computer and Communications Security)に発表した。コンピュータセキュリティ分野で最も権威ある査読付き国際会議のひとつだ。
実験の設計はシンプルだ。47人の参加者を2つのグループに分け、セキュリティに関係するプログラミングタスクを5種類こなしてもらった。一方のグループ(33人)はAIアシスタント(OpenAI の codex-davinci-002 ベース)を使える。もう一方のグループ(14人)は使えない。タスクの内容は暗号処理、メッセージ署名、ファイルシステム操作、SQLデータベース操作、C言語の文字列処理。いずれも実際の開発で使われる処理だ。
結果は、セキュリティの研究者が予想した方向ではあったものの、数字にすると重い。
発見1: AIを使ったほうが、安全でないコードを書いた
5つのタスクのうち4つで、AIを使ったグループのほうが安全でないコードを書いた。
最も顕著な差はメッセージ署名の処理だった。安全な実装を書けた参加者の割合は、AIなしグループでは21%、AIありグループでは3%だった。AIを使ったほうが正解率が7倍低い。
SQLデータベース操作タスクでは、AIありグループの36%がSQLインジェクション脆弱性のあるコードを書いた。AIなしグループでは7%だった。AIを使ったグループはSQLインジェクション脆弱性を5倍以上作りやすかったことになる。
// ❌ AIが生成しやすい(SQLインジェクション脆弱性あり)
// ユーザーの入力をそのまま文字列に埋め込む
async function getUser(email) {
const query = `SELECT * FROM users WHERE email = '${email}'`;
return await db.execute(query);
}
// ✅ パラメータ化クエリ(安全)
// 入力値をデータとして扱い、クエリ構造に混入させない
async function getUser(email) {
const query = "SELECT * FROM users WHERE email = ?";
return await db.execute(query, [email]);
}
2つのコードの機能は同じだ。通常のメールアドレスを入力すれば、どちらも正しくユーザーデータを返す。テストも通る。差が現れるのは、攻撃者が ' OR '1'='1 のような文字列を送ったときだ。上のコードはクエリが WHERE email = '' OR '1'='1' になり、全ユーザーのデータが返ってくる。
発見2: AIを使ったほうが、自信も高かった
ここからが問題の核心だ。
タスクを終えた参加者に「自分のコードはどれくらい安全だと思うか」を評価してもらった。AIありグループは安全でないコードを書いていた。それにもかかわらず、自分のコードの安全性の評価は、AIなしグループより高かった。
しかも研究はさらに興味深い傾向を示している。安全でないコードを書いた参加者ほど、AIをより信頼していた。逆に、AIへの信頼度が低く、プロンプトを言い換えたり試行錯誤したりしていた参加者のほうが、安全なコードを書いていた。
「AIを信頼している」ことと「安全なコードが生成された」ことは、むしろ逆相関していた。
なぜこうなるのか——「委任の感覚」が判断を鈍らせる
これは「AIが悪いコードを生成する」という単純な問題ではない。人間の心理の問題だ。
「安全になった」と感じると、人間はより大胆な行動を取る傾向がある。シートベルトの普及後、安全の知覚が運転速度を上げる行動につながるケースが繰り返し議論されてきた。リスクが下がったと知覚すると、人間は別のリスクを取る——「リスク補償」と呼ばれる心理現象だ。
AIアシスタントも同じ構造を作る。AIが「セキュリティを考慮してくれている感覚」を与えるからだ。
「この関数、AIが書いてくれた」という状態は、「この関数は誰かが責任を持ってくれている」という感覚を生む。自分で書いたコードなら「本当に安全か?」と立ち止まるところを、AIが関与したコードでは「AIが大丈夫にしてくれたはず」とスキップしやすくなる。
コードが整っていることも、この感覚を強める。コメント付き、変数名が明確、エラーハンドリングらしき記述がある。見た目がプロフェッショナルなコードに対して、人間は「ちゃんとしたものだ」という印象を持ちやすい。でも見た目とセキュリティは無関係だ。
「AIが書いた」ことは、セキュリティが確保された証拠ではない。AIは聞かれたことに答えるツールだ。「セキュリティを考慮してください」と明示的に要求しなければ、AIは機能要件だけを満たすコードを返す。
「動く」は確認できる。「安全」はそうではない
もう一つのコード例を見てほしい。APIキーの検証処理だ。
# ❌ 見た目は正しい。でもタイミング攻撃に脆弱
def verify_api_key(provided_key: str, expected_key: str) -> bool:
# APIキーが一致するか確認する
return provided_key == expected_key
# ✅ 定数時間比較(タイミング攻撃を防ぐ)
import hmac
def verify_api_key(provided_key: str, expected_key: str) -> bool:
# 比較時間を均一にして、文字ごとの差異を漏洩させない
return hmac.compare_digest(provided_key, expected_key)
2つの関数は機能的に同一だ。正しいキーを渡せば True、間違ったキーなら False を返す。テストは100%通る。
でも上の実装には「タイミング攻撃」という脆弱性がある。== による文字列比較は、最初の文字が一致しなければ即座にFalseを返す。一致すれば次の文字へ進む。攻撃者は大量のリクエストを送り、応答時間のわずかな差を測定することで、1文字ずつAPIキーを推測できる。
これはテストで発見できない。通常の使い方では問題が現れない。正しいキーも間違ったキーも、すべて期待通りの動作をする。
「コードが正しく動く」ことを確認する手段はある。「コードが安全である」ことを確認するには、別の視点が必要だ。
他の研究も同じ方向を示している
StanfordのCCS '23は単独の研究ではない。他の研究も同じ傾向を指摘している。
Maximilian SchreiberとPascal TippeによるICICS 2025での研究は、GitHubの公開リポジトリからAI生成コードのファイル7,703件を収集して分析した。Pythonでは16〜18%のファイルにCWEマッピング済みの脆弱性が見つかった。これは「90%近くは問題ない」と読むこともできるが、別の読み方もある——10本に1〜2本の割合で、見過ごされた脆弱性が本番コードに混在している。
The Register(2026年3月26日)が同時期に複数の研究をまとめた記事を掲載した。その中でジョージタウン大学のCSETによる研究(2024年11月)が引用されている。5つのLLMを対象にテストしたところ、生成されたコードスニペットの約48%はコンパイル可能だが何らかのバグを含んでいた。セキュリティ検証を通過したのは30%にとどまったという。
CodeRabbitが2025年12月に発表したレポートでは、470件のオープンソースPull Requestを分析した結果、AI生成コードのセキュリティ問題は人間が書いたコードの1.57倍多かった。XSSに至っては2.74倍だった。


AIへの信頼度が低かった参加者のほうが安全なコードを書いた
Stanfordの研究には、もう一つ注目すべき知見がある。
AIに対して懐疑的で、プロンプトを何度も書き直し、出力に批判的な目を向けていた参加者のほうが、安全なコードを書いていた。AIを「素直に信頼した」参加者ほど、結果が悪かった。
この傾向は感覚とも一致する。「AIが言うんだから大丈夫」とコードをそのままコピーペーストするのと、「AIが提案したがこれは本当に安全か?」と確認するのでは、結果が違う。
AIとの向き合い方は、「信頼するかしないか」ではなく、「何を委任して何を自分で判断するか」の問題だ。機能実装の加速にAIを使いながら、セキュリティの判断は自分で保持する——この分担が機能する。
実践的な対策——「AIが書いた」後に何をするか
確信バイアスを知った上で、では何を変えるか。
まず、セキュリティチェックを機能確認とは分けることだ。「動いた」の確認と「安全か」の確認は視点が違う。機能確認はユーザーの操作が期待通りに動くかを見る。セキュリティ確認は攻撃者が悪用できる経路がないかを見る。この2つを同じ作業として扱うと、どちらかが漏れる。AIに改めて「このコードにセキュリティの問題がないか」と聞くだけでも、視点を切り替えることができる。
次に、AIへの指示にセキュリティ要件を含めることだ。「ユーザー検索機能を作って」ではなく「ユーザー検索機能を作って。SQLインジェクション対策としてパラメータ化クエリを使うこと」と明示する。AIは聞かれなかったことを自動では守らない。要件に含めれば守る確率が上がる。
また、静的解析ツールを開発フローに入れることも有効だ。SemgrepやBandit(Python用)は、コードを実行せずにパターンで脆弱性を検出する。SQLインジェクションやXSSの典型的なパターンは自動で発見できる。AIを使ってもAIを使わなくても動くチェックを持つことが、「確信バイアス」への現実的な対抗手段だ。
Stanfordの研究で安全なコードを書いた参加者に共通していた行動は「AIをそのまま信用しなかった」ことだ。プロンプトを言い換える、出力を確認する、別の視点から見直す。AIの出力を素材として扱い、自分で判断する姿勢がセキュリティの差を生んでいた。
知らないことより、信じすぎることのほうが危険な理由
AIを使わない開発者は「自分はセキュリティに詳しくない」という自覚がある。知識の不足を知っている。だから調べる、確認する、慎重になる。
AIを使う開発者は「AIが助けてくれた」という感覚がある。不安が和らぐ。セキュリティ的な疑問が頭に浮かびにくくなる。結果として、確認のステップを省略しやすくなる。
Stanfordの実験が示したのはこの構造だ。安全でないコードを書いておきながら、安全だと信じていた——というのは、油断や怠惰ではない。AIが関与したことで、自然と生まれる認知の歪みだ。
バイブコーディングのリスクは「コードがわからない」ことだけではない。「わかった気になる」ことも、同じくらい現実的なリスクだ。

