結論から
AIで作ったアプリを公開する前に、自分の手でできる5分チェックの1つ目。URLの中の数字を1つ変えて開いてみてください。他人のデータが見えたら、サーバーが「本人かどうか」を確認していません。
この記事で伝えたいのは、この一点だけです。
- 自分の予約・注文・プロフィールのページを開くと、URLに
/reservations/12?id=12のような番号が入っている 12を13に変えて開き、他人のデータが表示されたら未修正。まだ公開できない- 原因は、サーバーが「13番は、いまログインしている人のものか」を確認せず、頼まれた番号をそのまま返していること
- 直すのはサーバー側の一行。AIへの頼み方と、直ったかの確かめ方を下に書いた
動画版(約2分)は本文の上に埋め込んであります。
① 何が起きるのか:数字を変えたら、他人の予約が見えた
例として、AIで作った美容室の予約アプリ(デモ用に用意したもの)で試します。
- 佐藤さんとしてログインし、自分の予約ページを開く。URLは
.../reservations/12 - アドレスバーの
12を13に書き換えて Enter - 表示されたのは 田中さんの予約。氏名・メールアドレス・電話番号・「ご要望」欄まで、そのまま読めた
14にすると別の人の予約で、「ご要望」欄には アレルギー情報 が書かれていた
このアプリは、予約する・変更する・確認する、すべての機能が問題なく「動いて」います。壊れているのは機能ではなく、「これを誰に見せてよいか」の判断です。
② なぜ起きるのか:理由は2つ
理由1:サーバーは、頼まれた番号を返しているだけ。
画面(クライアント)は「13番の予約をください」とサーバーに頼み、サーバーがデータを返しています。このとき、サーバーが「13番は、いまログインしている佐藤さんのものか」を確かめていなければ、13番でも14番でも同じように返してしまいます。前回の記事で見た「判断はサーバー側で」が、まさにここで抜けています。
理由2:URLは「お願い」であって、「鍵」ではない。
画面に13番へのリンクを出していなくても関係ありません。URLは誰でも自由に打てます。「リンクを置いていないから見えないはず」は、隠しているのではなく、「見に来ないでください」とお願いしているだけです。頼まれれば渡してしまう状態に変わりはありません。
この抜けは珍しいものではありません。Webアプリの代表的なリスクを毎年まとめている OWASP の「Top 10:2025」では、この種の「アクセス制御の不備」が第1位で、テストされたアプリの100%に何らかの不備が見つかったと報告されています。AIが書くコードでも同じで、Veracode が100以上のAIモデルに書かせたコードを検査した2025年の報告では、約45%にセキュリティ上の欠陥がありました。AIは「予約を表示する」という依頼は正しくこなしますが、「本人以外には表示しない」は、頼まれない限り書かないことが多いのです。
③ どう直すのか:サーバー側の一行を、AIに頼む
直すのは、「この予約は、ログインしている本人のものか」をリクエストごとに確認する一行です。以下をそのまま AI ツール(Cursor / Claude Code / Lovable のチャットなど)に貼ってください。
「IDで取得するすべての処理(予約・注文・ユーザー情報・アップロードファイルなど)で、そのデータがログイン中のユーザーのものかをサーバー側で確認してください。他人のデータなら403を返し、存在しないIDなら404を返すようにしてください。フロントエンド側でIDを隠すだけの対応は不要です。対象になった処理の一覧も出してください。」
Supabase を使っている場合は、もう一段深い対策として RLS(行レベルセキュリティ) をテーブルごとに有効にし、「user_id = auth.uid() の行だけ読める」ポリシーを付けます。これは「AIに頼むための言葉」シリーズで別途扱います。
④ 直ったかを確かめる:同じ手順で、もう一度
「直しました」というAIの返事は、確認の代わりになりません。もう一度 `13` を開いてください。
- 「表示できません」「見つかりません」などが出た → 合格
- ログイン画面に戻された → 合格(ログアウト状態で試した場合)
- さっきと同じ画面が出た → まだ直っていない
確認する場所は、数字のURLだけではありません。アップロードした画像のURL、請求書PDF、注文番号、招待リンク など、IDで取り出しているものはすべて同じ一行が必要です。先ほどのデモアプリでは、/uploads/license.jpg のようなURLを、ログインしていないシークレットウィンドウで開いたら、免許証の画像がそのまま表示されました。Supabase や Firebase のストレージも、設定によっては同じことが起きます(→ 個人情報の記事で詳しく)。
自分のアプリで試すときの手順は、①で見たとおりです。ログインして自分のデータのページを開く → URLの中の数字や長い文字列を見つける → 1つ変えて開く。別のアカウントか、シークレットウィンドウで 試すと、より確実です。
自分で直せないとき:エンジニアに送る一文
「なんとなく危ない気がする」では、依頼される側も何を見ればよいか分かりません。次の一文をそのまま送ってください。
「URLのIDを変えると他人のデータが見えます(例:/reservations/12 → /reservations/13)。本人確認をサーバー側に入れてください。画像URLやPDFなど、IDで取得している他の場所も同じ確認をお願いします。」
これだけで、直すべき場所が正確に伝わり、見積もりも具体的になります。逆に、この一文に「フロントでIDを隠せば大丈夫です」と返ってきたら、理由2をもう一度読んでください。その相手は避けたほうがよいです。
よくある質問
IDを推測しにくい長い文字列(UUID)にすれば、確認は不要になりますか。
推測は難しくなりますが、確認の代わりにはなりません。UUIDはメールの通知、共有リンク、ブラウザの履歴、スクリーンショットなどから漏れます。漏れた瞬間に同じ問題が起きるので、本人確認の一行は別途必要です。UUIDは「おまけの防御」と考えてください。
自分ひとりで使うアプリでも、この確認は必要ですか。
自分のデータしか入っていないなら、見えて困る相手がいないので優先度は低いです。ただし「あとで友人にも使ってもらう」「問い合わせフォームを付ける」と、他人のデータが入った瞬間に必要になります。公開の予定があるなら、最初から確認する習慣にしておくほうが早いです。
Lovable / Bolt / v0 で作りました。どこを見ればよいですか。
やることは同じです。デプロイ済みのURLを開いて、①の手順を試してください。多くの場合、データは Supabase に置かれています。その場合は Supabase の管理画面で対象テーブルの RLS が「Disabled」になっていないかも合わせて確認します。ここが赤い表示なら、URLを変える以前に、データベースそのものが外から読める状態です。
このチェックが通れば、公開して大丈夫ですか。
これは「公開前5分チェック」の1つ目にすぎません。管理画面がログインなしで開けないか、APIキーがフロントに書かれていないか、といった別のチェックが続きます。ひととおり自分で確かめたうえで、それでも不安が残る部分だけをエンジニアに見てもらうのが、いちばん費用対効果の高い順番です。VibeCode本番化では、そのための診断も行っています。


