AIで作ったアプリ、データが漏れていませんか? 10分でできるSupabaseチェック
Lovable や Bolt と Supabase で作ったアプリは、誰でも読めるテーブルのまま公開されていることがよくあります。10分で確認する方法と、最初に直すべき点を解説します。
4分で読めます
Lovable や Bolt などのツールで作ったアプリの多くは、データを Supabase に保存しています。これは良い選択です。Supabase は認証機能を備えた本物の Postgres データベースだからです。ただし、AIツールが必ずしも守らないルールがひとつあり、それが抜けていると、ブラウザの開発者ツールを開いただけで誰でもアプリのデータを読めてしまいます。
このガイドでは、何もインストールせずに、自分のアプリを約10分で確認する方法を紹介します。
アプリに入っているキーが公開されている理由
アプリはブラウザから Supabase と通信するため、ブラウザにキーが必要です。このキーは anon key(新しいプロジェクトでは publishable key)と呼ばれ、アプリの JavaScript に含まれています。誰でも見つけられますが、これは設計どおりです。
データを守っているのはキーではなく、Row Level Security(RLS) です。これは、訪問者ごとにどの行を読み書きできるかを決めるデータベース側のルールです。RLS が有効で適切なルールがあれば、公開キーは無害です。RLS が無効なら、公開キーでテーブル全体を読めてしまいます。
| 状態 | 公開キーを持つ第三者ができること |
|---|---|
| テーブルの RLS が無効 | すべての行を読める(多くの場合は変更も可能) |
| RLS 有効・ルールなし | 何もできない(すべてのリクエストが拒否される) |
RLS 有効・ルールが using (true) |
ルールの対象となる操作とロールについては、RLS 無効と同じ |
RLS 有効・ルールが auth.uid() に基づく |
ログイン中のユーザー自身の行だけ |
ステップ1:RLS が無効なテーブルを一覧にする
Supabase のダッシュボードでプロジェクトを開き、SQL Editor で次を実行します。
select c.relname as table_name,
c.relrowsecurity as rls_enabled
from pg_class c
join pg_namespace n on n.oid = c.relnamespace
where n.nspname = 'public'
and c.relkind = 'r'
order by c.relrowsecurity, c.relname;rls_enabled = false の行は、公開キーでアクセスできるテーブルです。Table Editor で作ったテーブルは初期状態で RLS が有効ですが、SQL で作ったテーブルは有効になりません。多くのAIツールは SQL でテーブルを作ります。
ダッシュボードの Security Advisor も、同じ問題を RLS Disabled in Public として表示します。エラーが出ていれば、まずそこから対応してください。
ステップ2:すべてを許可するルールを探す
RLS が有効でも、ルールが甘ければ同じように丸見えです。ルールを一覧にします。
select tablename, policyname, cmd, roles, qual, with_check
from pg_policies
where schemaname = 'public'
order by tablename, cmd;qual や with_check が単に true になっているルール、特に anon や public ロール向けのものに注意してください。profiles や orders のテーブルにそのようなルールがあれば、誰でもすべてのプロフィールや注文を読めるということです。
ステップ3:外部から確かめる
次に、攻撃者と同じ条件、つまり公開キーだけでテストします。Project Settings → API でプロジェクトの URL とキーを確認し、次を実行します。
curl "https://YOUR-PROJECT.supabase.co/rest/v1/profiles?select=*&limit=5" \
-H "apikey: YOUR_PUBLIC_KEY"結果の読み方:
- 自分以外のデータが返ってくる:テーブルが公開状態です。今日中に修正してください。
- 空のリスト
[]:テーブルが空か、RLS がすべてを除外しています。望ましい状態です。 - 権限エラー:そのテーブルには API から一切アクセスできません。これも問題ありません。
個人情報、決済、その他の非公開データを持つテーブルすべてで繰り返してください。
ステップ4:シークレットキーがアプリに入っていないか確認する
Supabase には service role key(または sb_secret_ で始まる secret key)もあります。これは RLS を完全に無視するため、必ずサーバー上だけで使う必要があります。公開中のアプリを開いて F12 を押し、Sources で JavaScript を service_role と sb_secret_ で検索してください。どちらかが見つかったら、すぐにダッシュボードでキーをローテーションし、そのキーを使っていた処理をサーバー側の関数に移してください。
最初に直すべきこと
- ブラウザに出てしまったシークレットキーをローテーションする。
- public スキーマのすべてのテーブルで RLS を有効にする:
alter table public.profiles enable row level security; - 非公開テーブルの
using (true)ルールを、ログイン中のユーザーに基づくルールに置き換える。 - ステップ3をもう一度実行し、第三者には何も返らないことを確認する。
RLS を有効にすると、公開状態のテーブルに頼っていた画面は動かなくなります。これは想定どおりで、各画面に必要な分だけを許可するルールが必要になります。AIが生成したアプリでどのルールが必要かわからない場合は、私たちの Security Check がまさにその作業から始めます。
SupabaseLovableRow Level SecurityAIで作ったアプリ
あわせて読みたい
記事一覧
アプリのセキュリティ
Supabase のシークレットキーがブラウザから見えていたら? 最初の1時間でやること
フロントエンドに service role キーやシークレットキーがあると、誰でもデータベースを自由に操作できます。無効化、差し替え、ログ確認、原因の修正という正しい順番を解説します。
6分で読めます

ウェブサイト
お問い合わせフォームのメールが迷惑メールに入る理由と、SPF・DKIM・DMARC による解決法
サイトのフォームから届くメールが迷惑メールに入る、または届かない。原因の多くは内容ではなく送り方です。確認すべき点と、設定すべき3つの DNS レコードを解説します。
5分で読めます