開発/設計

全コードの41%がAI製。1.7倍の重大問題を防ぐ"Vibe & Verify"3つの確認ステップ

AI生成コードは全体の41%に達した。だが共著コードには1.7倍の重大問題が潜む。CodeRabbit 470PR分析とMETR RCTの実証データをもとに、バイブコーディングの次のフェーズ「Vibe & Verify」を3ステップで実践する方法を解説する。

全コードの41%がAI製。1.7倍の重大問題を防ぐ"Vibe & Verify"3つの確認ステップ
目次

AIにコードを書かせる体験は、正直たまらない。

私はかつてエンジニアを挫折した人間だ。Cursor(カーソル)やClaude Code(クロードコード)を使い始めてから、凄腕エンジニアが自分に宿ったような感覚を得た。前回の記事ではClaude CodeのComputer Use(コンピューターユース)で画面操作まで任せる手順を紹介した。

ところが最近、気になるデータが次々と出てきている。

世界のコードの41%がAIで生成されている。その数、256億行。GitHubが2024年のOctoverseで公表した数字だ。米国では開発者の92%がAIを日常的に使っている。バイブコーディングはもう特別なことじゃない。

問題はここからだ。AI共著コードには1.7倍の重大問題が潜んでいる。セキュリティ脆弱性は2.74倍。誤設定は75%増。動いているのに壊れている。そんなコードが、世界中で量産されている。

この記事では”Vibe & Verify”(バイブ・アンド・ベリファイ)という考え方を紹介する。バイブコーディングで書く。そのあと検証する。この2段構えが、AIコーディング時代の新しい型になると私は確信している。

AIが書いたコードの41%、どこまで信じていいのか

BLUF: 全コード41%がAI製。だが品質面では「機能テスト合格61%のうち安全なのは10.5%」という現実がある。

2024年、世界で書かれたコードのうち41%がAI生成だった。GitHubのOctoverse 2024が公表した数字で、総量は256億行に達する。

この数字だけ見ると「AIすごい」で終わる。私も最初はそう思った。

ただ、裏を取ると見える景色が変わる。CodeRabbit(コードラビット)が470件のプルリクエストを分析した結果、AI共著コードは人間単独のコードと比べて1.7倍の重大問題を含んでいた。これは2025年12月に公開されたデータだ。

「重大問題」とは何か。具体的には以下のようなケースを指す。

  • 未処理のエラー: 例外が起きてもアプリが黙って落ちる
  • 認証バイパス: ログインなしでデータにアクセスできる穴
  • SQLインジェクション: データベースを外部から操作される脆弱性

人間単独コード vs AI共著コードの重大問題発生率を棒グラフで比較。AI側が1.7倍の高さ。注釈に「CodeRabbit 470PR分析、2025年12月」

METR(メトル)が実施したRCT(ランダム化比較試験)でも興味深い結果が出ている。AI支援を受けたエンジニアは、支援なしの場合と比べて作業完了が19%遅かった。速くなるはずのAIが逆に遅くしている。原因は「AIの提案を鵜呑みにしたレビュー時間の増加」と分析されている。

CS(カスタマーサクセス)の仕事をしていた私には、この構図が妙に馴染む。「ツールを入れれば生産性が上がる」と信じて導入した結果、運用コストが跳ね上がるパターン。業務ツールで何度も見てきた光景だ。

問題はAIが悪いのではない。検証の仕組みがないのが問題なのだ。

“Vibe & Verify”とは何か。バイブコーディングに検証を足す新しい型

BLUF: “Vibe & Verify”は「AIに書かせる→自分で検証する」の2段構え。バイブコーディングの進化形として2026年に定着しつつある。

バイブコーディングという言葉は、Andrej Karpathy(アンドレイ・カルパシー)が2025年に提唱した。「雰囲気でコードを書く」という意味で、AIにやりたいことを伝えて、出てきたコードをそのまま動かすスタイルを指す。

この手法は間違いなくゲームチェンジャーだった。私のように一度コードから離れた人間が、再びプロダクトを作れるようになった。

とはいえ、規模が大きくなると問題が出てくる。

前回の記事で紹介したClaude Code Computer Useを使えば、画面操作まで自動化できる。できることが増えた分、見落とすリスクも増えている。

“Vibe & Verify”は、このリスクに対する答えだ。

やり方はシンプル。3つのステップで構成される。

  1. Vibe(バイブ): AIに書かせる。いつも通りのバイブコーディング
  2. Pause(ポーズ): 一呼吸置く。別セッションを開く
  3. Verify(ベリファイ): 検証する。3つの確認ステップを回す

「え、検証って面倒じゃないですか?」と思うかもしれない。

正直に言う。面倒だ。ただ、面倒の度合いが違う。バグを本番で踏んでから直す面倒さに比べたら、10分の検証は安い投資だと思う。

私が業務ツールを作っていた時、テストなしで社内リリースしたことがある。翌日の朝会で「数字がおかしい」と指摘された。原因を追うのに3時間。検証に10分かけていれば防げた問題だった。

確認ステップ1: 生成と検証を別セッションに分ける

BLUF: AIに書かせたセッションと、検証するセッションを物理的に分ける。同じ文脈で確認すると、AIの自己肯定バイアスに引きずられる。

これが最も重要なステップだ。

Claude Codeでコードを生成した後、そのまま同じセッションで「このコード大丈夫?」と聞いてはいけない。AIは自分が書いたコードを肯定する傾向がある。人間だって自分の企画書を自分でレビューしたら甘くなるのと同じだ。

具体的な手順を示す。

# ステップ1: バイブコーディングで機能を実装(セッションA)
claude "ユーザー登録APIを作って。メール認証付きで"

# ステップ2: 新しいセッションを開いて検証(セッションB)
claude --new-session
# 検証用プロンプト
claude "このファイルのセキュリティ上の問題点を5つ挙げて: src/api/register.ts"

ポイントは --new-session だ。新しいセッションには前の文脈が引き継がれない。だからAIは「自分が書いたコード」という意識なしに、客観的にレビューできる。

左にセッションA(生成)、右にセッションB(検証)を並べたフロー図。間に「コンテキスト断絶」の壁を示す

私はこの方法を「壁打ちレビュー」と呼んでいる。CS時代、お客さまのクレーム対応で使っていた手法の応用だ。当事者が書いた回答文を別の人がチェックする。当事者はどうしても防衛的になるから、第三者の目が必要になる。

AIも同じ構造だ。生成したセッションのAIは「作り手」になっている。別セッションのAIは「レビュアー」として機能する。

実際にやってみると、驚くほど指摘が出る。

  • 「この認証トークンの有効期限が設定されていません」
  • 「レート制限がないため、ブルートフォース攻撃に脆弱です」
  • 「エラーメッセージにスタックトレースが含まれています」

同じセッションで聞いたら「問題ありません」と返ってきた指摘が、別セッションだと具体的に出てくる。この差は体験すると衝撃的だ。

確認ステップ2: AIに「なぜそう書いたか」を説明させる

BLUF: コードの意図をAIに言語化させることで、「動くけど理由がわからない」ブラックボックスを解消する。説明できないコードは危険信号。

バイブコーディングの落とし穴の1つに「動くけど、なぜ動くかわからない」がある。

私も何度も経験した。Claude Codeが生成したコードを実行したら期待通りに動いた。嬉しい。でも3ヶ月後の自分がこのコードを見た時、何をしているか理解できるだろうか。

ステップ2では、AIに「なぜ」を説明させる。

# 生成されたコードの意図を確認する
claude "src/api/register.ts の各関数について、
なぜその実装方針を選んだのか説明して。
特に以下の3点:
1. なぜこのバリデーション順序なのか
2. なぜこのエラーハンドリング方式なのか
3. 他にどんな選択肢があったのか"

返ってきた説明が腑に落ちなかったら、それは赤信号だ。

たとえば「パフォーマンスのために非同期処理にしました」と説明されたのに、実際にはI/Oが1回しか発生しない処理だった。こういうケースでは、AIが「それっぽい理由」を後付けしている可能性が高い。

逆に、説明が筋の通ったものであれば安心材料になる。

この確認で得た説明をコメントとしてコードに残すのも有効だ。

// register.ts
// バリデーション順序: メール形式→重複チェック→パスワード強度
// 理由: DB問い合わせ(重複チェック)の前に軽い検証を済ませ、
// 不正入力の大半をDBアクセスなしで弾く設計
async function validateRegistration(input: RegistrationInput) {
  validateEmailFormat(input.email);    // 軽い検証を先に
  await checkDuplicateEmail(input.email); // DB問い合わせは後
  validatePasswordStrength(input.password);
}

CS出身だからこそわかることがある。ユーザーが「なぜこうなっているの?」と聞いた時に答えられないシステムは信頼されない。コードも同じだ。

ちなみにこの手法、チーム開発にも応用が効く。自分が書いたコードの意図をAIに要約させて、プルリクエストの説明文に貼る。レビュアーの負担がぐっと減る。私は社内ツール開発でこれを始めてから、レビューの差し戻しが半分以下になった。

確認ステップ3: 1機能1テストを自動生成する

BLUF: AIにテストも書かせる。ただし「テストを書いて」ではなく「このコードが壊れるケースを5つ考えて、それぞれテストにして」と頼む。

テストを書くのは退屈だ。私も正直、テストを書くのは好きじゃない。

だからこそAIに任せる。ただし頼み方が重要だ。

# NG: 漠然とした依頼
claude "register.ts のテストを書いて"

# OK: 壊れるケースから考えさせる
claude "register.ts が壊れるケースを5つ考えて。
それぞれについて:
1. どんな入力で壊れるか
2. なぜ壊れるか
3. テストコードを書いて"

「壊れるケース」から考えさせると、AIは防御的な視点でコードを分析する。単に「テストを書いて」だと、正常系のテストばかり出てくる。異常系こそ本番で問題になるのに。

// AIが提案した「壊れるケース」の例
describe("ユーザー登録API", () => {
  // ケース1: SQLインジェクション攻撃
  it("メールアドレスにSQL文を含む入力を拒否する", async () => {
    const malicious = "admin'--@example.com";
    await expect(register({ email: malicious }))
      .rejects.toThrow("Invalid email format");
  });

  // ケース2: 同時登録によるレースコンディション
  it("同一メールの同時登録で片方がエラーになる", async () => {
    const input = { email: "test@example.com", password: "Str0ng!Pass" };
    const results = await Promise.allSettled([
      register(input),
      register(input),
    ]);
    const rejected = results.filter(r => r.status === "rejected");
    expect(rejected.length).toBe(1); // 片方だけ失敗
  });

  // ケース3: 極端に長い入力
  it("10,000文字のメールアドレスを拒否する", async () => {
    const longEmail = "a".repeat(10000) + "@example.com";
    await expect(register({ email: longEmail }))
      .rejects.toThrow();
  });
});

Vibe & Verifyの3ステップを縦に並べたフロー図。Step1「セッション分離」→Step2「意図の言語化」→Step3「破壊テスト生成」。各ステップに

このテストを実行して全部通ったら、少なくとも「よくある壊れ方」は防げている。完璧ではないにしても、テストゼロの状態とは雲泥の差だ。

所要時間は3つ合わせて約10分。コーヒーを1杯入れる間に終わる。

ハマりポイントを先に共有しておく。「テストを書いて」だけだと、AIはimportパスを間違えることがある。テスト対象のファイルパスを明示的に渡すのがコツだ。「src/api/register.ts をimportしてテストを書いて」と言えば、パスのズレで実行が失敗する問題を避けられる。

「完璧なコード」を目指さない。「壊れにくいコード」を目指す

BLUF: Vibe & Verifyのゴールは完璧ではない。「本番で致命的に壊れない」を担保することだ。バイブコーディングの速度を殺さず、最低限の安全を確保する。

ここで大事なことを言っておきたい。

Vibe & Verifyは完璧主義の道具ではない。プロのエンジニアが書くような堅牢なテストスイートを目指しているわけじゃない。

私の哲学は変わっていない。「とりあえず動くもん作ろう」が最初。そのあとに「致命的に壊れないか確認しよう」を足すだけ。

以前の記事で紹介したバイブコーディングの落とし穴、CurXecute(カーゼキュート)脆弱性の話を覚えているだろうか。Cursor CEOが自ら「脆い基盤」と認めた事件だ。あの問題も、生成後に別セッションでセキュリティチェックを走らせていれば検出できた類のものだった。

CodeRabbitの分析が示すセキュリティ脆弱性2.74倍というデータは怖く見える。ただ、これは検証なしで本番に出した場合の話だ。10分の検証を入れるだけで、このリスクは大幅に減る。

CodeRabbitが指摘しているのは「AIが悪い」ではなく「AIの出力をそのまま信じると危ない」ということ。包丁が危険なのではなく、包丁の扱い方の問題と同じだ。

私がCS時代に学んだことがある。「導入支援で一番大事なのは、ツールの使い方ではなく、ツールを疑う視点を持ってもらうこと」。AIコーディングにも同じ原理が当てはまる。

3つの検証ステップを実行した場合と未検証の場合の、重大問題発見率の比較イメージ。未検証は赤ゾーン、検証済みは緑ゾーン

まとめ: バイブコーディングは終わらない。次のフェーズに進むだけ

AIが書くコードの量はこれからも増える。41%が50%になり、60%になるだろう。

その流れを止める必要はないし、止めるべきでもない。バイブコーディングのおかげで、かつての私のように挫折した人間が再びコードを書けるようになった。この革命を手放すつもりはない。

ただし「書いたら終わり」の時代は終わった。

“Vibe & Verify”の3ステップをもう一度整理する。

  1. セッションを分ける: 生成と検証を別の文脈で行う(3分)
  2. 意図を説明させる: 「なぜそう書いたか」をAIに言語化させる(3分)
  3. 壊れるケースでテストを作る: 「壊れる方法」から逆算してテスト生成(5分)

合計10分。この10分が、3時間のバグ修正を防ぐ。

私はこれからもバイブコーディングで作り続ける。業務ツールも、個人プロダクトも。ただし、作ったあとに10分だけ立ち止まる。

「動いてる。で、安全?」

この問いを自分に投げかける習慣が、バイブコーディングの次のフェーズだと思っている。もう一回やってみませんか。今度は検証付きで。


参考リンク

ゲン
Written byゲンCS × Vibe Coder

正直、一度エンジニアは諦めました。新卒で入った開発会社でバケモノみたいに優秀な人たちに囲まれて、「あ、私はこっち側じゃないな」って悟ったんです。その後はカスタマーサクセスに転向して10年。でもCursorとClaude Codeに出会って、全部変わりました。完璧なコードじゃなくていい。自分の仕事を自分で楽にするコードが書ければ、それでいいんですよ。週末はサウナで整いながら次に作るツールのこと考えてます。