LovableとSupabaseを使うときのセキュリティ注意点|Auth・RLSを確認

LovableとSupabaseを使うときのセキュリティ注意点。Lovableなどを対象に、向き不向きが分かるように整理します。

AIものさし編集部

LovableとSupabaseをつないだアプリでは、ログイン画面が動くことだけでは安全確認になりません。公開APIから直接tableへrequestできる構成では、各tableでRow Level Security(RLS)を有効にし、databaseのgrantsとpolicyの両方を確認します。ユーザー用のpublishable keyはブラウザへ置けますが、アクセス範囲を守るのはRLSと権限設定です。secret keyやlegacyのservice_role keyはRLSを迂回するため、client codeへ置かないでください。

この確認を終えた状態とは、未ログイン利用者・ユーザーA・ユーザーB・管理者のそれぞれで、読める行と書ける行を説明でき、直接APIへアクセスしても想定外のdataが返らない状態です。LovableのSecurity表示が問題なしでも、実際のtable policyやgrantを代わりに保証するものではありません。公開対象と認証方式を決めてから、以下の順で確認します。

まずAuthとauthorizationを別の問いにする

Authentication(Auth)は「誰がログインしているか」を確認します。Authorizationは「その人がこのrecordを読んだり変更したりしてよいか」を決めます。ログイン済みでも、他人の行を読めるpolicyならデータは守られていません。

SupabaseのAPI keyもユーザー本人を表すものではありません。keyはブラウザ・serverなど、どのapplication componentがprojectへアクセスしているかを識別します。ログイン中の個人はSupabase AuthのJWTで別に識別され、RLS policyはそのidentityを使って行ごとのアクセスを制限します。

表は横にスクロールできます

用語答える質問例
API keyどのapplicationから来たrequestかbrowser用のpublishable key
Auth誰がログインしているかSupabase Authのユーザー
Grantそのroleにtable操作を許すかselectだけ許可する
RLS policyどの行にその操作を許すかuser_idが本人と一致
Server secret信頼できるserverからの特権操作かsecret keyを使うbackend

key名ではなく、実行場所と権限で分ける

Supabaseは新しい形式のpublishable keyとsecret keyを案内しています。publishable keyはブラウザなど利用者に配布される場所で使う前提で、単独ではユーザーdataへの広い権限を与えません。実際に許可される操作はtable grants、RLS policy、認証状態で決まります。

secret keyはserver、Edge Functionなど管理下の実行環境へ置きます。Supabaseの公式説明ではsecret keyはRLSを迂回する権限を持つため、漏れるとpolicyが防御になりません。以前から使われているanonはpublishable相当のlegacy key、service_roleはsecret相当のlegacy keyです。名前にanonが入るからsecret、またはservice_roleを通常のブラウザkeyとして扱うのは誤りです。Supabaseは旧anon / service_role keyを2026年末までに非推奨化する予定を案内しています。新規実装ではpublishable / secret形式を基本にし、既存projectではDashboardの移行表示と残存利用箇所を確認してください。既存projectでは新旧keyが同時に有効な場合があるため、現在のDashboardと利用中コードを照合してください。

LovableのSecretsへ入れた値も、どこで使うかで安全性は決まりません。client bundleへ埋め込まれる環境変数に特権keyを入れれば、名前をsecretにしてもブラウザ利用者から見える可能性があります。生成されたコードの参照箇所を確認し、秘密値がserver-side functionだけに渡る構成にしてください。

RLSは有効化、policy、grantsを一組で確認する

Supabaseの公式手順では、公開schemaで使う各tableについてRLS、必要なgrants、operationごとのpolicyを確認します。RLSを有効にしただけでは、正しい利用者に必要な操作が許可されません。一方、policyを作っても広すぎるtable grantが残っていれば、意図した制御にならない場合があります。特に既存projectでは既定grantの状態を確認します。

ここでは、各noteにuser_idがある単純な例を考えます。実際に実行するSQLではなく、policyの形を理解するための見本です。table名・型・roleが自分のschemaと一致するか確認してから使います。

alter table public.notes enable row level security;

create policy "read own notes"

on public.notes for select to authenticated

using ((select auth.uid()) = user_id);

create policy "insert own notes"

on public.notes for insert to authenticated

with check ((select auth.uid()) = user_id);

create policy "update own notes"

on public.notes for update to authenticated

using ((select auth.uid()) = user_id)

with check ((select auth.uid()) = user_id);

selectでは読み取り対象を、insertでは新規行の所有者を、updateでは変更前と変更後の両方を制限する例です。deleteも必要なら、別途対象roleと行条件を決めます。「RLSを有効にしたから全操作が適切」とは考えず、操作別に許可と拒否を定義してください。

まずは使ってみる

記事の文脈に合うToolへ進めます。報酬の有無で見た目は変えていません。

未ログイン・別ユーザーを使うテスト表

実装後は、管理画面上の設定だけでなく、独立した利用者で許可と拒否の両方を試します。テスト用のrecordを作り、他人の実dataを触らないでください。

表は横にスクロールできます

実行者読み取り追加変更・削除
未ログイン公開が必要なdataだけpolicyで許可した場合だけ原則拒否、必要なら条件を明記
ユーザーAA所有の行だけAのuser_idで作成Aの行だけ
ユーザーBB所有の行だけBのuser_idで作成Bの行だけ
管理者機能管理者の認可後だけserver側で必要分だけoperationと対象を記録

特に「ユーザーAがURLやrequest bodyのuser_idを書き換えてBの行を読めないか」を確かめます。UIから他の行へのlinkを隠すだけでは不十分です。APIへ直接requestしても同じ境界で拒否される必要があります。Supabase公式はpolicyをtable操作ごとに試し、許可ケースと拒否ケースをテストする方法を示しています。

Table以外の経路も棚卸しする

RLSを確認したtable以外にも、データが外へ出る経路があります。view、RPC、Edge Function、Storage、外部API連携は個別に確認します。Supabaseではviewの作成方法によって基礎tableのRLSがそのまま適用されない場合があり、関数がservice roleで動くなら関数内部の認可も必要です。Storageもbucketの公開設定とobject policyを別に見ます。

確認のたびに「どのrequestで何が返るか」を残してください。たとえば、ログイン中のAがBのrecord IDを指定したとき、空配列・権限エラー・404のどれを返すかは実装次第です。大事なのは特定のresponse文字列ではなく、Bのdataを取得・更新できないことです。誤って許可したら、画面を直すより先にgrant、policy、server側の権限経路を修正します。

LovableのSecurity表示は補助レビューとして使う

LovableのSecurity機能やSecurity best practicesは、設定・権限・露出の見落としを探す手がかりになります。ただし、表示上の指摘がないことと、利用者間の分離が実証されたことは同じではありません。tableごとのpolicy、実際のAuth状態、generated functionのservice-role利用、Storage、公開APIを人が確認します。検査結果が古くなり得るなら、schemaや認証変更後にもう一度確認してください。

最後に、コードや設定へ秘密値を含めていないかをrepository diffとbuild outputでも確認します。secretを画面でmaskするだけでは漏えい対策の完了になりません。keyが露出した場合は値を消すだけでなく、該当keyをrotateし、過去のlogや配布済みbundleにも残っていないかを調べます。

AIものさしの判断

小規模な試作でも、ログインを付けて個人データを扱うなら、AuthとRLSの確認を公開前の必須作業にします。ブラウザ用のpublishable keyが見えること自体を秘密漏えいと混同せず、そのkeyで取得できるdataをpolicyとgrantで狭めます。反対に、secret / service_role keyはRLSを迂回するため、clientへ出た時点で重大な問題として扱います。

ユーザーごとのデータ境界を実際にtestできない、あるいはLovable CloudとSupabaseのどちらが保存先なのか分からないなら、公開を保留します。まず保存先、table、role、操作ごとの許可条件を1枚の表にし、未ログイン・A・Bのテスト結果を揃えてから公開判断へ進んでください。安全性はsecurity scanの表示だけでなく、許可してよい行だけが実際に返ることまで確かめて判断します。

次の一手

記事の内容を踏まえて、公式とTool詳細から続けられます。

次に読む・使う

この記事の次に必要な情報へ進めます。

ツールの詳細