本文へ移動

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 で次を実行します。

public スキーマのテーブルと RLS の状態
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 が有効でも、ルールが甘ければ同じように丸見えです。ルールを一覧にします。

public スキーマのすべての 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_ で検索してください。どちらかが見つかったら、すぐにダッシュボードでキーをローテーションし、そのキーを使っていた処理をサーバー側の関数に移してください。

最初に直すべきこと

  1. ブラウザに出てしまったシークレットキーをローテーションする。
  2. public スキーマのすべてのテーブルで RLS を有効にする:alter table public.profiles enable row level security;
  3. 非公開テーブルの using (true) ルールを、ログイン中のユーザーに基づくルールに置き換える。
  4. ステップ3をもう一度実行し、第三者には何も返らないことを確認する。

RLS を有効にすると、公開状態のテーブルに頼っていた画面は動かなくなります。これは想定どおりで、各画面に必要な分だけを許可するルールが必要になります。AIが生成したアプリでどのルールが必要かわからない場合は、私たちの Security Check がまさにその作業から始めます。

SupabaseLovableRow Level SecurityAIで作ったアプリ

この記事は次の言語でも読めます: EnglishPortuguêsEspañol中文

記事一覧