開発/設計

バイブコーディングの45%に穴。三部作の最終回で、予防の設計を全部書いた

AI生成コードの45%にセキュリティ脆弱性が存在する。業界全体の構造問題が初めて定量化された今、バイブコーディングに予防の設計を組み込む方法を、三部作の最終回として解説する。

バイブコーディングの45%に穴。三部作の最終回で、予防の設計を全部書いた
目次

45%。

この数字が、三部作を書いてきた意味を証明してくれている。

第1弾では、Lovable(ラバブル)製アプリ170個の裏口を追った。第2弾で紹介したのは、生成後に検証する”Vibe & Verify”(バイブ・アンド・ベリファイ)の3ステップだ。

最終回のテーマは業界全体の構造問題になる。AI生成コードの45%にセキュリティ脆弱性がある。daily.dev(デイリードットデブ)の調査が、バイブコーディングのリスクを初めて定量化した数字だ。

“1つの事件”が”業界の数字”へ変わった瞬間を見ている。

三部作の最終回では”予防の設計”を書く。発見して、検証して、その先にある”最初から穴を作らない仕組み”。バイブコーディングの速さを殺さずにセキュリティを担保する方法を、全部出し切りたい。

45%の正体。セキュリティリスクが”業界の数字”で初めて可視化された

AI生成コードの45%にセキュリティ脆弱性。92%の開発者が使い、新コードの60%がAI製。問題は特定ツールではなく、コーディングの主流に存在している。

Lovableの10.3%は衝撃的だった。とはいえ「1つのプラットフォームの話」と受け流す余地はあったと思う。

今回の45%は、そうはいかない。

daily.devの調査によると、AI生成コードの45%にセキュリティ上の脆弱性が存在する。対象はLovable単体ではない。主要なバイブコーディングツール全体にまたがるデータだ。

規模感を整理しておきたい。

  • 米国開発者の92%がバイブコーディングを日常採用
  • 2026年の新規コードの60%がAI生成
  • そのうち45%にセキュリティ脆弱性あり

掛け算すると見えてくる。世界で新しく書かれるコードのかなりの割合に、穴が空いている計算になるわけだ。

GitHub(ギットハブ)のOctoverse 2024によると、AI生成コードは全体の41%に達した。総量は256億行だ。CodeRabbit(コードラビット)の470件PR分析では、AI共著コードに1.7倍の重大問題が含まれると判明していた。

45%という数字は、個別の発見を”業界全体の構造問題”に格上げするものだと思う。

「92%がAIを使用→60%がAI生成コード→45%に脆弱性」の3段階ファネル図。上段は青、中段はオレンジ、下段は赤でリスク拡大を可視化

正直に書いておく。45%の一次ソースはdaily.devの記事だ。調査の母集団サイズや脆弱性の定義について、詳細が公開されていない部分もある。数字を鵜呑みにするより、「業界全体でリスクが顕在化している」という傾向として読み取るのが正しい姿勢だろう。

それでも、この数字が出てきた意味は大きい。「1つのアプリに穴がある」と「業界全体の半分近くに穴がある」では、対策のスケールが根本的に異なるからだ。

三部作の地図。発見→検証→予防で何が見えたか

第1弾で”事件”を知り、第2弾で”検証の型”を得た。最終回で”予防の仕組み”を入れて完結する。カスタマーサクセスの障害対応と同じ構造だ。

三部作は偶然に始まった。

3月末、Lovableの脆弱性が報じられた時のことを覚えている。1,645個のアプリをスキャンして170個に穴が見つかったデータを読んだ瞬間、記事にしなければと思ったのが出発点だ。それが第1弾「170個の裏口」になっている。

書き終えた後、「で、自分のコードはどう確認すればいいの?」という問いが頭に残った。その答えが第2弾「Vibe & Verify」だ。生成と検証を別セッションに分ける。AIに意図を説明させる。壊れるケースでテストを作る。3つの確認ステップを10分で回す方法を提案した。

ただし、検証は事後対応でしかない。穴が空いてから塞ぐ作業だ。

45%という数字を見て気づかされた。事後に塞ぐだけじゃ追いつかない。最初から穴を作らない仕組みの設計が求められている。

テーマ役割
第1弾(4/1)Lovable 170個の裏口発見。何が起きているかを知る
第2弾(4/14)Vibe & Verify 3ステップ検証。生成後に確認する方法
第3弾(今回)予防の設計予防。最初から穴を作らない仕組み

CS出身だからこそピンとくる構造がある。この流れは、カスタマーサクセスの障害対応フローと同じなのだ。「インシデント発生→根本原因分析→再発防止策」。第1弾がインシデント報告、第2弾が分析、今回が再発防止にあたる。

問題を知っているだけでは足りない。検証する手段を持っているだけでも不十分だ。仕組みとして予防できて初めて、バイブコーディングは”安心して使える道具”になれるはずだ。

予防の設計、3つのレイヤー。プロンプトからCI/CDまで一気通貫で守る

予防は”プロンプト→テンプレート→自動ゲート”の3層構造だ。バイブコーディングの速度を維持しながら、セキュリティを仕組みとして組み込む方法を紹介する。

“予防の設計”と聞くと大げさに感じるかもしれない。私も最初はそう思っていた。

実際にやってみたら、想像よりシンプルだった。3つのレイヤーに分けると整理しやすくなる。

レイヤー1: プロンプトにセキュリティ要件を焼き付ける

最も手軽で、最も効果が高い方法がこれだ。

AIにコードを書かせる時、「ユーザー登録APIを作って」だけでは不十分だと第1弾で学んでいる。RLSが設定されないまま本番に出た原因は、まさにここにあった。

# NG: 機能だけ伝える
「ユーザー登録APIを作って」

# OK: セキュリティ要件を含めて伝える
「ユーザー登録APIを作って。
 要件:
 - RLSを有効化。ユーザーは自分のデータだけ読み書きできるポリシーを設定
 - APIキーは環境変数から取得(フロントエンドに直書き禁止)
 - ユーザー入力はパラメータバインディングで処理
 - レート制限を設定(1分あたり10リクエスト上限)」

この差は劇的だ。第1弾で紹介したLovableの事例では、RLSの未設定が18,000人のデータ漏洩につながっている。プロンプトに数行追記するだけで防げた問題だった。

私は今、CLAUDE.mdファイルにセキュリティ要件のデフォルトを書いている。Claude Code(クロードコード)はプロジェクトルートのCLAUDE.mdを自動的に読み込む仕様だ。毎回プロンプトに書く手間がなくなるのが嬉しい。

# CLAUDE.md に追記するセキュリティデフォルト例

## セキュリティ要件(全コード共通)
- データベーステーブル作成時はRLSを必ず有効化すること
- シークレットは環境変数から取得。ハードコード禁止
- ユーザー入力は必ずサニタイズしてから処理
- 認証が必要なエンドポイントにはミドルウェアを設定
- エラーレスポンスにスタックトレースを含めない

一度書けば、そのプロジェクト内の全リクエストに適用される。「セキュリティ要件を書き忘れる」というリスク自体が消えるのが最大の利点だと感じている。

レイヤー2: VibeContractをセキュリティテンプレート化する

第1弾で紹介したVibeContract(バイブコントラクト)を覚えているだろうか。AIに対する「契約書」のような仕組みだ。

あの時は概念の紹介にとどまった。今回は実際に運用中のテンプレートを出す。

# vibecontract-security.yaml
# バイブコーディング用セキュリティ契約テンプレート

version: "1.0"
project: "my-app"

security_contracts:
  database:
    - "全テーブルにRLSを有効化"
    - "ポリシーは最小権限の原則に従う"
    - "管理者ロールのポリシーは別途定義"

  secrets:
    - "APIキーとトークンは.envから取得"
    - ".envファイルは.gitignoreに含める"
    - "フロントエンドに渡すキーはANON_KEYのみ"

  input_validation:
    - "SQLクエリはパラメータバインディング必須"
    - "HTMLレンダリング時はXSSエスケープ処理"
    - "ファイルアップロードはMIMEタイプ検証"

  authentication:
    - "認証エンドポイントにレート制限を設定"
    - "トークン有効期限は24時間以内"
    - "パスワードはbcryptでハッシュ化"

このYAMLファイルをプロジェクトルートに置くだけでいい。AIにコード生成を依頼する際は「vibecontract-security.yamlの契約に従って」と一言添える。セキュリティ要件が自動的に反映される。

ポイントはYAML形式で書いていること。人間にもAIにも読みやすい。新しいメンバーがプロジェクトに参加した時、セキュリティ方針が一目で把握できるのも副次的なメリットだ。

レイヤー3: CI/CDでをデプロイ前にブロックする

最後のレイヤーは自動化になる。人間は忘れる。AIも指示がなければ省略する。だから仕組みで防ぐしかない。

# GitHub Actionsの例: セキュリティスキャンをCIに組み込む
# .github/workflows/security-scan.yml

name: Security Scan
on: [push, pull_request]
jobs:
  scan:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      # Supabase RLSチェック
      - name: Check RLS policies
        run: |
          # マイグレーションファイルからCREATE TABLEを検索
          # RLSが有効化されていないテーブルを検出
          TABLES=$(grep -rn "CREATE TABLE" supabase/migrations/ \
            | grep -oP 'CREATE TABLE \K\w+')
          for table in $TABLES; do
            if ! grep -q "ENABLE ROW LEVEL SECURITY" \
              supabase/migrations/*; then
              echo "ERROR: $table にRLSが未設定です"
              exit 1
            fi
          done

      # シークレット漏洩チェック
      - name: Scan for exposed secrets
        uses: trufflesecurity/trufflehog@main
        with:
          path: ./

このワークフローが動いていれば、RLS未設定のテーブルやシークレットの漏洩がプルリクエストの段階で検出される。本番環境に穴が到達する前にブロックできるわけだ。

3層の予防設計を縦に並べた構造図。Layer1「プロンプト(手動)」→Layer2「VibeContract(半自動)」→Layer3「CI/CDゲート(全自動

3つのレイヤーを全部導入する必要はない。レイヤー1のプロンプト改善だけでも、45%のリスクのかなりの部分を潰せると実感している。自分の規模に合った層から始めればいい。

自分のコードを今日診断する。45%に入っていないかの確認手順

第2弾のVibe & Verify 3ステップに加え、今回は「予防が機能しているか」の診断リストを用意した。5分で完了する。

予防の仕組みを導入したとしても、「本当に機能しているか」を確認しないと安心できない。

第2弾では生成後の検証を書いた。今回は予防の動作確認だ。以下の5項目を手元のプロジェクトでチェックしてみてほしい。

#確認項目確認方法期待する結果
1CLAUDE.mdにセキュリティ要件があるかファイルを開いて目視確認RLS・シークレット・入力検証の3項目が記載
2.envが.gitignoreに含まれているかcat .gitignore | grep .envヒットする
3フロントエンドにシークレットが露出していないかgrep -r "sk-|AKIA|stripe_sk" src/ヒットしない
4データベースのRLSが有効かSupabase(スーパベース)ダッシュボードで確認全テーブルでEnabled
5CIにセキュリティスキャンが入っているか.github/workflows/ を確認スキャン用ジョブが存在する

5項目すべてクリアなら、45%の穴からはかなり距離がある。1つでも引っかかったら、今日中に対処するのが望ましい。

ハマりポイントを先に共有しておく。チェック3の grep は、ビルド済みファイル(dist/build/)も対象にすべきだ。ソースコードには書いていなくても、ビルド時に環境変数がインライン展開されるフレームワークがある。Next.js(ネクストジェイエス)の NEXT_PUBLIC_ プレフィックスが典型例だろう。これは”公開前提”の変数なので、シークレットを絶対に入れてはいけない。

もう1つ注意点がある。チェック4でRLSが「Enabled」と表示されていても油断は禁物だ。第1弾で書いた通り、Lovable 2.0のスキャナーは「有効かどうか」しか見ていない。「正しく機能しているか」は未検証だった。ポリシーの中身まで確認する必要がある。

“動けばOK”の先にある景色。三部作を書き終えて思うこと

完璧なセキュリティは目指さない。致命的な穴を塞ぐだけでいい。予防の設計はバイブコーディングの速度を殺さず、むしろ加速させる。

私の哲学は変わっていない。「とりあえず動くもん作ろう」が出発点だ。

三部作を通じて学んだのは、“動けばOK”と”穴を放置してOK”が全く違うということだった。動くことは大前提。そのうえで、致命的な穴だけは最初から塞いでおく。

かつてプロのエンジニアには敵わないと思った。それは今も変わっていない。アーキテクチャの深い設計では、あの日出会った凄腕たちに遠く及ばないだろう。

一方で、自分のアプリに穴がないかを確認するのはプロじゃなくてもできる作業だ。CLAUDE.mdにセキュリティ要件を5行書く。VibeContractのテンプレートをコピペする。CIにスキャンジョブを1つ足す。どれも10分以内で終わる。

45%という数字を見て、正直怖いと思った。

でも同時に、希望も感じている。

なぜなら原因が明確だからだ。RLSの未設定。シークレットの露出。入力検証の不備。第1弾から第3弾まで一貫して同じ原因が繰り返されている。原因がわかっているなら、対策も明確に立てられる。

METR(メトル)のRCTではAI支援で作業が19%遅くなったと報告されている。原因はAIの提案を鵜呑みにしたレビュー時間の増加だ。予防の設計を入れれば、この検証の負荷そのものが減ると考えている。最初から安全なコードが生成されるのだから、事後チェックの項目が少なくて済むはずだ。

予防は”開発を遅くする仕組み”ではない。“速くても安全に走れる道路”を整備する作業だ。

三部作を書き始めた時、「バイブコーディングは危険だ」と言いたかったわけではなかった。「安全に使いこなす方法を共有したい」が動機だ。Lovableの170個の裏口も、45%の脆弱性も、「やめろ」ではなく「進化しろ」というシグナルだと受け取っている。

凄腕エンジニアが自分に宿る感覚は、本物だ。今もそう確信して疑わない。AIのおかげで、一度挫折した私がまたコードを書けるようになった。この体験を手放すつもりはまったくない。

ただし、安全装置は自分で付ける。それが三部作の結論だ。

まとめ: 45%の穴を、3つのレイヤーで塞ぐ

バイブコーディング×セキュリティ三部作が完結した。

第1弾で170個の裏口を知った。第2弾で検証の型を手に入れた。最終回の今回は、予防の設計を3層で組み立てている。

  • レイヤー1(プロンプト): CLAUDE.mdにセキュリティ要件を一度書けば、全リクエストに自動適用される。最も手軽で効果が高い
  • レイヤー2(テンプレート): VibeContractでセキュリティ契約を定義する。YAMLファイルをプロジェクトルートに置くだけで運用できる
  • レイヤー3(自動ゲート): CI/CDにセキュリティスキャンを組み込む。RLS未設定やシークレット露出をデプロイ前にブロックする

45%のAI生成コードに脆弱性がある世界で、自分のコードを守る責任は自分にある。完璧を目指す必要はない。致命的な穴を塞ぐ。それだけで十分だと思っている。

三部作を通じて、一つの確信が強くなった。バイブコーディングを「危険だからやめよう」と結論づける記事は、書きたくなかった。そうではなく、「安全装置を付けた状態で、もっと速く走れる」ことを証明したかった。今回の3レイヤー設計は、その答えの一つだ。

3本とも読んでくれた方には、改めて感謝を伝えたい。バイブコーディングで何かを作っているすべての人に、「もう一回、安全装置付きで作ってみませんか」と言い残して三部作を閉じる。


参考リンク

ゲン
Written byゲンCS × Vibe Coder

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