バイブコーディング セキュリティ、Lovable事件2ヶ月後の更新3つ
Lovable製アプリ170個に穴が見つかった2026年4月から2ヶ月。あの時の予防処方箋を今、どう書き換えるか。実装基準の更新点3つを整理しました。
この記事でわかること
- 本文に入る前に、まず押さえるべき結論
- 開発や実装の判断が、ここからどう変わるか
- 次に読むべき関連記事の入口
この記事で扱うこと
- Lovable事件(4月の170/1,645アプリ・10.3%)から2ヶ月、業界の議論が「穴の存在認知」から「実装基準の更新」に移ったこと
- 私自身が4月に書いた予防三部作(170個の裏口・45%脆弱性・Tenzai 15アプリ69穴)を、6月時点でどう書き換えるかの更新3点
- 今週から30分・15分・60分で動かせる最小実装3点
読者の前提: バイブコーディング(CursorやClaude Code、Lovable等のAIコード生成)を使い始めて1〜3ヶ月。「動けばOK」で進めてきたが、セキュリティの基準が自分の中にないと感じている開発者・PM。 私は4月、バイブコーディングのセキュリティについて三部作を書きました。Lovable製アプリ1,645件中170件に脆弱性が見つかった事件。Veracodeが報じた45%の生成コードに穴がある話。Tenzaiが15アプリで69個の穴を見つけた比較レポート。書いた当時の私の処方箋は「とりあえずSAST入れて、環境変数分けて、生成物をレビューしましょう」でした。
それから2ヶ月。同じテーマを今書くなら、処方箋を3つ書き換えると思っています。理由は1つ。「動いた瞬間に止めて見るレビュー」では、検知できない種類の穴が出てきたから。
この記事は、4月の自分の処方箋を6月の自分が書き換える試みになります。Infosecurity関連の業界議論を観測しつつ、ファクトとして確定しているのは私が4月に書いた数字と、私自身の業務ツール実装ログ。そこから「今週変えられる最小実装3点」まで落としていきますね。
Lovable事件から2ヶ月、何が変わったか
まず数字を1つ確定させます。4月、Lovable製アプリ1,645件のうち170件(10.3%)にセキュリティ欠陥が見つかりました。これは私が4月1日の記事で扱った数字で、当時は「バイブコーディング普及の裏側」として書いたものです。
2ヶ月経って、業界の議論はどう変わったか。私の観測では3つの段階がありました。
第1段階(4月)認知期。「AI生成コードに穴がある」という事実が、専門家以外にも届いた時期。私の記事もこの波の一部でした。読者からの反応で多かったのは「やっぱりそうですよね」「うちの社内ツールも見直します」という”気づきの声”。
第2段階(5月)検知期。「で、どう検知するの?」が論点になった時期です。多くの記事や勉強会で「SAST(Static Application Security Testing)を入れましょう」「Snykを回しましょう」「Semgrepでカスタムルールを書きましょう」という処方箋が共有されていました。私自身、4月の三部作の最終回(16日)で「予防の設計」として静的解析パイプラインの組み方を扱っています。
第3段階(6月)追跡期。ここが今回の更新点になります。検知ツールを入れた人たちが、次の壁に当たっているんですね。「ツールがOKと言ったコードでも、穴がある」「ツールが止めた箇所が、実は問題なかった」。誤検知と検知漏れの両方が積み上がってきました。

なぜ第3段階になったか。私なりの仮説は1つあります。バイブコーディングで生成されるコードは、人間が書いたコードとは「穴の出方」が違うんですよ。人間のコードは「うっかり認証チェックを忘れる」が典型的な穴です。一方AI生成コードは「もっともらしい認証ロジックを書くが、別の場所で副作用的に権限が漏れる」という穴の出方をしてくる。穴が”見えるところ”ではなく”つながり”に潜む。SASTは構文解析が中心なので、つながりベースの穴を見つけにくいんです。
私が4月に書いた処方箋は、第2段階の議論に最適化されたものでした。SAST入れて環境変数分けて生成物をレビュー。これは間違いではありません。ただしそれだけでは止まらないことが、2ヶ月後の今わかってきました。
ここから、6月時点で追加すべき更新点を3つ書きます。
【更新点1】SASTを補う「なぜ」の追跡。プロンプトログを証跡として残す
1つめの更新点は、プロンプトログを保存することです。
私が4月に書いた処方箋は「生成されたコードをレビューする」でした。これは正しいんですけど、レビューする時に「なぜこのコードが生成されたか」の情報が手元にない。生成プロンプト(私がAIに何を頼んだか)と、その時の文脈(どのファイルを開いていたか、どんな指示を出したか)が、レビュー時点で消えてるんですよ。
これが第3段階の壁を作っているんです。「もっともらしい認証ロジックだが、別の場所で副作用がある」コードを見た時、レビュアーは「なぜここに権限チェックを入れなかったの?」と聞いてきます。書いた人は「いや、私もよくわからなくて……AIに任せたら、こう出てきて」と答える。この時、プロンプトログが残っていれば原因が特定できる。「AIに渡した文脈に、別ファイルの権限チェックが入っていなかったので、AIは”既存の権限チェックがある前提”で書いた」と読み解けるからです。穴の責任主体が人間かAIかではなく、文脈の渡し方にあったとわかる。
具体的に何をするか。Cursorなら設定の cursor.chat.exportHistory を有効化してチャット履歴をローカル保存できます(2026年6月時点の機能名です。バージョンによって変わる可能性があります)。Claude Codeの場合は ~/.claude/projects/ 配下に会話ログが自動保存される作りになっています。
# Claude Code の会話ログ確認例
ls -la ~/.claude/projects/
# 各プロジェクトディレクトリ配下に
# 会話履歴のJSONLが残る作り(実装はバージョンに依存)
これだけだと「ログがあるだけ」なので、もう1歩進めましょう。コミットメッセージに、生成プロンプトの要約を入れるルールを作ります。
feat: 認証ミドルウェア追加
AI-prompt-summary:
- 「JWT検証ミドルウェアを書いて。既存のlogger.tsと
同じスタイルで」と依頼
- 既存の権限テーブル構造はAIに渡していない
- 戻り値の型は手動で調整
このAI-prompt-summary欄が、後でレビュー時の手がかりになるんですよ。3時間溶かしたら3分で通過できる、というのと同じで、1コミットあたり30秒の追記が、後の3時間のデバッグを止める設計です。
ハマったポイントを先に言うと、最初は「全プロンプトを丸ごとコピペ」しようとしていました。これは続きません。3日でやめました(経験済みです)。要約だけ・3行以内にすると、自然に定着する。私は1ヶ月、このルールで運用中です。
【更新点2】「動けばOK」を止めるレビューゲート2段化
2つめの更新点は、レビューゲートを2段に分けることです。
4月の処方箋では「生成物を必ずレビューする」と書きました。これは正しいんですが、1段のレビューだと「動くか・動かないか」の判定に流れがちです。動けばマージ、動かなければ直す。「動くけど穴がある」コードが、すり抜けます。
私が今やっているのは2段ゲートです。
第1ゲート: 機能レビュー。「これ動く?」「テスト通る?」「仕様満たしてる?」を見る。ここは速いです。15分くらい。
第2ゲート: 文脈レビュー。「このコード、何を前提にしている?」「前提が崩れた時、どう壊れる?」を見る。ここは時間がかかります。30分〜1時間。
第2ゲートのチェック項目をまとめました。
| チェック項目 | 何を確認するか | NGの例 |
|---|---|---|
| 入力の信頼境界 | 外部入力をどこで検証しているか | リクエストボディを直接DB.findに渡している |
| 認証の境界 | 認証チェックがどのレイヤーにあるか | 認証はミドルウェアで一度だけ、内部呼び出しはノーチェック |
| 環境変数の扱い | シークレットがどう注入されているか | コード内にハードコーディング、または.envがgitに含まれる |
| 外部API呼び出し | 失敗時の挙動が定義されているか | try-catchなし、または握りつぶしのcatch |
| 権限の漏れ | ある操作の前後で権限状態が変わるか | adminチェックの後にロール変更可能になっている |
このチェックリスト、4月の私は持っていませんでした。5月に2件、6月に1件、自分の業務ツールで「動くけど穴があった」コードを通してしまって、その時の反省を整理したものです。

実装としては、PRテンプレートに第2ゲートのチェック項目を埋め込みます。GitHubなら .github/PULL_REQUEST_TEMPLATE.md に書く。GitLabなら Merge Request Templateに置きます。チェックリストにあると、レビュアーは”このチェック、見ました?“と聞ける。これがないと「動いてるからマージしていいですよね」で終わってしまうんです。
ハマりポイント。チェック項目を10個以上にすると形骸化します。5項目までに絞る。私は5項目で運用しています。
【更新点3】生成物の「起源」を追跡する仕組み
3つめの更新点は、生成物の起源(origin)を追跡する仕組みです。
これが一番、4月時点で書けていなかった部分になります。当時の私は「人が書いたコードもAIが書いたコードも、結局は本番に出るコードなんだから、レビューさえすれば同じ」と思っていました。
2ヶ月使ってわかったのは、起源情報を残さないと”なぜ”が再現できないということ。バグが見つかった時、コードの出元が区別できないと再発防止策が作れません。「これはCursorのChat由来」「Claude CodeのEdit由来」「Lovable由来」と分けて記録する必要があるわけです。
私が今やっているのは、ファイル単位ではなくコミット単位で起源を記録する方法。
# コミットフックで自動付与する例
# .git/hooks/prepare-commit-msg に以下を追加
#!/bin/bash
# 環境変数 AI_TOOL に書き込んでいるツール名が入っている前提
if [ -n "$AI_TOOL" ]; then
echo "" >> $1
echo "Generated-by: $AI_TOOL" >> $1
fi
AI_TOOL=cursor で起動すればCursor由来、AI_TOOL=claude-code ならClaude Code由来、と記録される仕組みです。完璧ではないんですが、ないよりずっとマシ。
この仕組みが何の役に立つか。バグが3件出た時に起源の偏りが見えるんですよ。「3件中2件がLovable由来」「3件中3件がCursorのComposer機能由来」のように分布が見える。すると「Cursor Composerでは権限チェック周りを任せない」というローカルなルールが作れる。穴の出方とツールの相性が、データで残るわけですね。
これは大企業の話ではありません。1人で業務ツールを作っている私のような立場でも、3ヶ月で30コミット、半年で60コミットの起源情報が貯まれば、自分の選択の偏りが見えてきます。Claude Codeの社内導入パターンはClaude Code全社展開、KAGが設計が詳しい。個人ツールでも、ツール別の相性を記録する習慣は同じように使えます。
ハマりポイント。起源情報はコミットメッセージに自動で入れる仕組みにしないと書き忘れますよ。私は最初、手動で書いていて2週間で挫折しました。フックで自動化するのが正解です。
今週から動かせる最小実装3点
ここまでの3つの更新点を、今週から動かせる最小実装に圧縮していきますね。

最小実装1: プロンプトログ保存設定(所要30分)
Claude Codeを使っているなら、~/.claude/projects/ 配下のログがすでに残っているはずです。確認だけ。Cursorを使っているなら、設定からチャット履歴の永続化を有効にする。1回設定すれば後は勝手に残ります。
# Claude Code のログ確認
du -sh ~/.claude/projects/
# サイズが0でなければOK。ログは残っている
# Cursor の場合は設定画面で
# Settings > Features > Chat > Export History を有効化
最小実装2: PRテンプレに第2ゲート欄追加(所要15分)
GitHubのリポジトリなら、.github/PULL_REQUEST_TEMPLATE.md を作る。中身は以下を貼り付けるだけ。
## 機能レビュー(第1ゲート)
- [ ] テスト通る
- [ ] 仕様を満たしている
## 文脈レビュー(第2ゲート)
- [ ] 入力の信頼境界を確認した
- [ ] 認証チェックが各レイヤーにある
- [ ] シークレットがコード/設定/環境変数のどこにあるか明示した
- [ ] 外部API失敗時の挙動を定義した
- [ ] 権限の漏れ(操作前後で権限が変わる可能性)を確認した
## AI生成情報
- 生成ツール:
- プロンプト要約(3行以内):
これだけで、レビュアーが「このチェック、見ました?」と聞ける状態が手に入ります。
最小実装3: SASTスキャンをCIに1本だけ追加(所要60分)
GitHub Actionsを使っているなら、Semgrepの無料プランを1本だけ追加してみてください。
# .github/workflows/sast.yml
name: SAST Scan
on:
pull_request:
branches: [main]
jobs:
semgrep:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: returntocorp/semgrep-action@v1
with:
# Semgrep Registryの公開ルールセットを使う
config: p/default
Semgrepは無料プランでも公開ルールセット(p/default、p/security-audit等)が使える仕様。最初は p/default だけで十分です。誤検知が出るので、PR上にコメントとして出る方式で慣れる。ブロッキング(マージ拒否)にするのは、運用が3週間続いてから。最初からブロッキングにすると、誤検知で開発が止まって全員が嫌いになります。
ここで私のハマりポイントを1つ。Semgrep Registryの p/owasp-top-ten を最初から入れたら、誤検知が100件以上出てPRが見れなくなりました。p/default から始めるのが正解です。
4月の予防三部作と組み合わせる読み方
最後に、今回の更新3点と、4月の予防三部作をどう組み合わせるかをまとめます。
4月の三部作で書いたこと(再確認):
- Lovable事件170個の裏口(4月1日): バイブコーディング普及の裏で「動くけど穴がある」アプリが大量に公開されている事実
- 45%脆弱性予防三部作最終回(4月16日): SAST/環境変数分離/レビューを軸にした予防の設計
- Tenzai 15アプリ69穴(4月23日): 5大エージェント比較で見えたツール別の穴の出方
これらに今回の更新3点を重ねると、こうなります。
| 4月の処方箋 | 6月の更新 |
|---|---|
| SASTを入れる | SASTは継続。ただし「ツールがOK」と言っても通さない第2ゲートを追加 |
| 環境変数を分離 | 継続。さらに「シークレットがどこにあるか」をPRで明示 |
| 生成物をレビュー | レビューを2段化(機能/文脈)。プロンプトログを証跡として残す |
| ツールの穴の出方を知る | 「生成物の起源」を記録して、自分の選択の偏りをデータで見る |
更新点はどれも4月の処方箋を否定するものではありません。4月の3点は今も有効。その上に**「動くけど穴がある」を止めるための仕組み**を3つ追加する、という関係になります。
私自身、4月の三部作を書いた時点では「とりあえず動くもん作ろう」の精神でやっていました。今もその精神は変わりません。ただし「動くもの」の定義に”穴がない”が含まれるようになった。挫折組のエンジニアとしては、これは大きな前進だと思っています。
プロには敵わない。でも自分の仕事を楽にするコードなら書ける。書いたコードに穴がないかは、自分で見られるようにする。プロは見えなかった穴も見えるけど、私たちは見える穴を全部塞ぐ。ツールの力を借りて、見える穴の範囲を広げていく。これがバイブコーディング2年目に入る私たちの戦い方なんですよ。Claude Code自体の使い方の地図はClaude Code 始め方、3つの判断とにナギがまとめてくれています。まだ環境構築段階の方はそちらから先にどうぞ。
Lovable事件は事故ではなく、業界全体への問いかけでした。問いに対して、4月時点での答えと、6月時点での答えは違っていい。処方箋は更新する前提で書くものです。私はまた2ヶ月後に、6月の自分の処方箋を書き換えていると思います。
その時にこの記事を読み直して、「ああ、6月の自分はここで止まってたな」と笑える日が来るのが、私の楽しみです。
この記事のまとめ
- Lovable事件170/1,645件(10.3%)から2ヶ月。業界の議論は「認知期」「検知期」「追跡期」の3段階で進んだ
- 4月の予防三部作(SAST/環境変数/レビュー)は今も有効。その上に3つの更新点を重ねる
- 更新点1: プロンプトログを証跡として残し、コミットに3行要約を入れる
- 更新点2: レビューを機能/文脈の2段ゲートにする。文脈レビューは5項目チェック
- 更新点3: 生成物の「起源」をコミットメッセージで自動記録し、ツール別の穴の偏りをデータ化
- 今週から: プロンプトログ設定30分・PRテンプレ追加15分・SAST 1本追加60分
挫折組のエンジニアこそ、穴の塞ぎ方を1つずつ覚えていける。2ヶ月後の更新を楽しみに、また書きます。

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


