開発/設計

バイブコーディングの170個の裏口。Lovable製アプリ10.3%にセキュリティ欠陥が見つかった件を、元・挫折エンジニアが本気で調べた

Lovableで作られたアプリの10.3%にセキュリティ欠陥が見つかったという調査結果を徹底解説。バイブコーディングの安全性をエンジニア目線で本気で調べた。

バイブコーディングの170個の裏口。Lovable製アプリ10.3%にセキュリティ欠陥が見つかった件を、元・挫折エンジニアが本気で調べた
目次

「動いてるのに穴だらけ」が1,645個のアプリで証明された

昨日まで「バイブコーディングの落とし穴」を一般論として書いていた私に、具体的な数字が突きつけられました。

Superblocks(スーパーブロックス)の調査レポートによると、バイブコーディングプラットフォームLovable(ラバブル)で作られたアプリ1,645個をスキャンした結果、170個に重大なセキュリティ欠陥が見つかったそうです。全体の10.3%。脆弱なエンドポイントは303箇所に達していました。

10個に1個ですよ。

漏洩データの中身がまた衝撃的でした。Google MapsやGemini(ジェミニ)のAPIキー、eBayの認証トークン、ユーザーの個人情報、金融取引データ。The Register(ザ・レジスター)の報道では、1つのアプリだけで18,000人分のユーザーデータが露出していた事例も報告されています。

私がこの記事を書いているのは、「Lovableが悪い」と言いたいからじゃありません。昨日の記事で書いた「動いているのに壊れている」症候群が、想像以上の規模で現実になっていたことに衝撃を受けたからです。

この記事では、何が起きたのかを正確に整理し、自分のコードを今日チェックできる3つの手順を共有します。バイブコーディングを「使うかどうか」の話はもう終わった。今日からは「どう安全に使うか」のフェーズに入ったんです。

CVE-2025-48757: 何が起きていたのか

技術的な話を噛み砕いて説明しますね。

今回の脆弱性にはCVE-2025-48757という正式な識別番号が付いています。CVEとは、世界共通のセキュリティ脆弱性データベースの番号のこと。つまり「ちょっとしたバグ」ではなく、国際的に認定された深刻な問題ということです。

発見者はセキュリティ研究者のMatt Palmer(マット・パーマー)氏。Palmer氏の公開声明によると、最初にLovable CEOのAnton Osika(アントン・オシカ)氏に連絡したのは3月21日。Lovable側は3月24日に受領を確認。しかし45日間の開示猶予期間内に実質的な修正が行われず、公表に至ったという経緯です。

CVE-2025-48757の発見から公表までのタイムライン。3/21発見者連絡→3/24受領確認→45日間猶予→5/29公表の流れを時系列で表示

原因はRLSの欠如

問題の核心はRLS(Row Level Security)の未設定です。RLSとは、データベースの行単位でアクセス制御をかける仕組みのこと。「このユーザーは自分のデータだけ見られる」「管理者だけが全データを閲覧できる」といったルールを設定するものです。

LovableはバックエンドにSupabase(スーパベース)を採用しています。データベース接続用の認証トークン(anon key)はフロントエンドのJavaScriptに含まれる仕様。RLSが正しく設定されていれば、これは問題になりません。

ところがLovableのAIは、データベースのテーブルを作成する際にRLSポリシーを設定していなかったんです。テーブルは作る。データの読み書きもできるようにする。でも「誰がアクセスできるか」のルールは空っぽのまま。結果として、anon keyさえ持っていれば誰でもデータベースの中身を丸ごと読み書きできる状態になっていました。

SecurityOnline(セキュリティオンライン)の詳報でも、この構造的な問題が指摘されています。

CS出身だからこそ言えるんですけどね。これってWebポータルのログイン画面は立派に用意したのに、URLを直接叩けば誰でも管理画面に入れる状態と同じ。玄関はロックしたけど裏口が全開。だから「170個の裏口」と呼んでいるわけです。

Lovable 2.0の「セキュリティスキャン」は不十分だった

Lovableは2025年4月24日に「Lovable 2.0」をリリースし、セキュリティスキャン機能を搭載しました。しかしdesplega.ai(デスプレガ)の分析によると、スキャナーはRLSが「有効かどうか」だけをチェックする仕様。「正しく機能しているか」までは検証しなかったそうです。

つまり、穴の空いたRLSポリシーでも「設定済み」と表示される。ユーザーに誤った安心感を与える結果になった。これは「治療」ではなく「絆創膏」だと批判されています。

Lovableだけの問題じゃない。バイブコーディング全体の構造的リスク

「自分はLovable使ってないから関係ない」と思いましたか。私も最初はそう思いました。でも調べていくと、もっと大きな話だと気づいたんですよね。

Escape.tech(エスケープテック)の調査は衝撃的です。対象はLovableだけじゃありません。Base44、Create.xyz、Bolt.newなど複数プラットフォームの5,600以上のアプリを分析しています。ただし調査対象のうち約4,000アプリがLovable製であり、プラットフォーム間のサンプル偏りがある点には留意が必要です。

結果はこうでした。

  • 2,000件以上の脆弱性を発見
  • 400件以上のシークレット(APIキーやパスワード)が露出
  • 175件のPII(個人を特定できる情報)が漏洩。医療記録、銀行口座番号、電話番号、メールアドレスを含む

Getautonoma(ゲットオートノマ)のレポートでは、AIが生成したコードの53%にセキュリティ上の穴があるという数値も報告されている。半分以上ですよ。

なぜAIはセキュリティ設定を「忘れる」のか

ここが本質的な問いです。

AIは「動くコードを書く」ことには非常に優秀。ユーザーが「ユーザー登録機能を作って」と頼めば、フォーム、バリデーション、データベースへの保存まで一気に組み上げてくれる。しかしセキュリティ設定は「動作に必要ない」ために、明示的に指示しないと省略されがちなんです。

RLSを設定しなくても、アプリは動く。データは保存できるし、画面も表示される。「動いているのに壊れている」の典型例そのものです。

私が昨日の記事で書いたSlack Botの話を思い出してください。SQLインジェクション対策が入っていなかったあのコード。構造は全く同じなんですよね。AIは機能を実装するけれど、防御は実装しない。頼まれていないから。

vietanh.dev(ビエットアン)のガイドでも、この「機能実装と防御実装の非対称性」がバイブコーディングの根本的な課題として指摘されています。

# AIが「ユーザー登録を作って」と頼まれた時に生成するコード例
# 機能としては完璧に動く。でもRLSが設定されていない

# Supabaseのテーブル作成(AIが生成しがち)
# → RLSポリシーが空っぽ = 誰でもアクセス可能
create_table_sql = """
CREATE TABLE users (
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  email TEXT NOT NULL,
  name TEXT,
  created_at TIMESTAMPTZ DEFAULT now()
);
"""

# 安全な書き方: RLSを最初から有効にする
secure_table_sql = """
CREATE TABLE users (
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  email TEXT NOT NULL,
  name TEXT,
  created_at TIMESTAMPTZ DEFAULT now()
);
-- RLSを有効化
ALTER TABLE users ENABLE ROW LEVEL SECURITY;
-- 認証済みユーザーが自分のデータだけ読めるポリシー
CREATE POLICY "users_read_own"
  ON users FOR SELECT
  USING (auth.uid() = id);
"""

この2つのコード、動作上の違いはありません。どちらもユーザーを登録できる。でも上のコードは「裏口全開」で、下のコードは「鍵付き」。たった数行の差が、18,000人分のデータ漏洩を防ぐかどうかの分岐点になるんです。

今すぐ確認すべき3つのセルフチェック

ここからは実践パートです。「自分のコードは大丈夫か?」を今日中に確認できる3つの手順を紹介します。

チェック1: Supabaseダッシュボードでテーブル一覧を確認する

Supabaseを使っている人は、管理画面にログインしてください。左メニューの「Table Editor」を開き、各テーブルの「RLS」列を確認する。「Disabled」と表示されているテーブルがあったら、それが裏口です。

確認手順は3ステップ。

  1. Supabaseダッシュボードにログイン
  2. 左メニュー「Authentication」→「Policies」を開く
  3. 各テーブルにポリシーが設定されているか確認する

ポリシーが1つも設定されていないテーブルがあれば、要対応。「RLS Enabled」でもポリシーが空なら、有効化されているだけで実質的には無防備です。Lovable 2.0のスキャナーが見逃したのも、まさにこのパターンでした。

チェック2: フロントエンドのソースコードでAPIキーを検索する

ブラウザの開発者ツール(F12キー)を開いて、「Sources」タブでJavaScriptファイルを確認してみてください。検索窓に以下のキーワードを入れて探す。

// ブラウザの開発者ツールで検索すべきキーワード
// 1つでもヒットしたら、そのキーは露出している

sk-          // OpenAI APIキーのプレフィックス
AKIA         // AWS アクセスキーのプレフィックス
AIza         // Google APIキーのプレフィックス
ghp_         // GitHub パーソナルアクセストークン
stripe_sk_   // Stripe シークレットキー

Supabaseのanon keyが見つかるのは正常です。それは公開前提のキーだから。問題は、上記のようなシークレットキーがフロントエンドに埋め込まれている場合。これは今すぐ環境変数に移動してください。

ブラウザ開発者ツールのSourcesタブでAPIキーを検索している画面のスクリーンショット風イラスト。検索窓に「sk-」と入力し、ハイライトされた結果が表示され

チェック3: AIに「攻撃者視点」でレビューを依頼する

昨日の記事でも紹介した手法ですが、今回の文脈でさらに具体的なプロンプトを共有します。

このアプリケーションのセキュリティを
攻撃者の視点でレビューしてください。
特に以下の3点を重点的にチェック:

1. データベースのアクセス制御
   (RLSポリシーは設定されているか?)
2. APIキーやシークレットの露出
   (フロントエンドに埋め込まれていないか?)
3. ユーザー入力のサニタイズ
   (SQLインジェクション・XSS対策は十分か?)

各項目について、脆弱性がある場合は
具体的なコード修正案を示してください。

ポイントは「攻撃者の視点で」という一言。これを入れるだけで、AIの出力が「問題ないですね」から「ここが突破口になります」に変わる。別セッションで依頼するのも忘れずに。コードを生成した会話の中で頼むと、自作自演になりがちです。

「使うかどうか」の議論は終わった

ここで一歩引いて考えてみたいんですよね。

Semafor(セマフォア)の報道では、Lovableが「ハッカーにとって格好の標的」と表現されていました。こういう見出しを見ると「やっぱりバイブコーディングは危険だ」と思う人もいるでしょう。

でも私はそう思わないんです。

思い出してほしいのは、Webアプリケーション開発の歴史。2000年代、PHPで作られたサイトはSQLインジェクションだらけでした。WordPressの脆弱性は今でも毎月のように報告されています。だからといって「PHPを使うな」「WordPressを使うな」とはならなかったですよね。ツールが成熟し、ベストプラクティスが確立され、セキュリティ対策が標準装備になっていった。

バイブコーディングも同じ道をたどっているだけだと、私は考えています。

実際、動きは始まっている。Escape.techは$18Mの資金調達を完了し、バイブコーディング専用のセキュリティスキャナーを構築中です。VibeEvalというLovable特化の自動セキュリティテストサービスも登場しました。

ツール側の対応も進んでいます。Claude Codeはセキュリティリスクの警告機能を搭載しつつある。Cursorもコード生成時にリスクを提示する方向で進化中。GitHub Copilotの新メトリクスAPIでは、AIが生成したPRの品質追跡も可能になった。

「使うかどうか」の段階はとっくに過ぎました。Barrack AI(バラックAI)のまとめによると、2025年1月以降のAIアプリ関連データ漏洩は20件。根本原因はほぼ共通しています。アクセス制御の欠如、シークレットの露出、入力検証の不備。原因がわかっているなら、対策もできるはず。

問題は「バイブコーディングが危険かどうか」ではなく「あなたのコードに裏口が開いているかどうか」です。

昨日の記事とつなげて考える

昨日、私は「動いているのに壊れている」症候群の3つの落とし穴を書きました。セキュリティの穴、説明できないコード、テストなしの砂の城。そしてVibeContractという対処法を紹介した。

今日のLovable事件は、あの記事の「セキュリティの穴」が現実世界で大規模に発生した事例そのものです。しかも私が「理論的にはこういうリスクがある」と書いたことが、1,645個のアプリで実証されてしまった。

昨日紹介したVibeContractのyamlに1行追加するだけで、今回のような事故は防げた可能性が高い。

# vibecontract.yaml に追加すべき1行
contracts:
  - "全テーブルにRLSを有効化し、適切なポリシーを設定する"
  - "APIキーは環境変数から取得。フロントエンドに直書きしない"
  - "ユーザー入力は必ずパラメータバインディングで処理する"

「契約に書いてあるから、AIが自動で設定する」。この仕組みがあれば、170個の裏口のうちかなりの部分が閉じられていたはず。バイブコーディングの速さを殺さず、品質を守る。昨日と今日の記事を合わせて読んでもらえれば、その全体像が見えるようになっています。

「昨日の記事(一般論)→今日の記事(具体事件)」の関係を示す接続図。左に3つの落とし穴アイコン、右にLovable 170個の裏口アイコン。中央に矢印で「予測が

まとめ: 裏口を閉じるのは、あなた自身の判断

Lovableの170個の裏口から学べることを整理します。

  • 何が起きたか: 1,645アプリ中170個(10.3%)にRLS未設定の脆弱性。APIキー・個人情報・金融データが露出
  • なぜ起きたか: AIは「動く機能」を作るが「防御」は頼まれなければ省略する。バイブコーディング全体に共通する構造的課題
  • 今日できること: Supabaseダッシュボードでテーブルのポリシー確認、フロントエンドのAPIキー検索、AIへの攻撃者視点レビュー依頼
  • 中期的な対策: VibeContractでセキュリティ要件を「契約」として事前定義する

私は「動けばOK」が信条の人間です。それは変わらない。でも裏口が開いたまま放置するのは話が別。凄腕エンジニアが自分に宿る感覚は本物だけれど、セキュリティの判断まで宿ってくれるわけじゃないんですよね。

かつてプロのエンジニアには敵わないと思った。今もアーキテクチャの深い設計では敵わないかもしれない。でも「自分のアプリに裏口がないか確認する」はできる。今日紹介した3つのチェックは、プロじゃなくても5分で終わる作業です。

バイブコーディングは武器になる。ただし安全装置を外したまま振り回すのは、自分を傷つけるだけ。170個の裏口は「バイブコーディングが危険だ」という証拠ではありません。「安全な使い方を学ぶタイミングが来た」というシグナルだと受け取っています。

あなたのアプリの裏口、今日中に確認してみてください。5分で済みますから。

ゲン
Written byゲンCS × Vibe Coder

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