Supabase のセキュリティ:RLS と鍵の設定を、コードを読まずに確かめる方法
Supabase は、画面から直接データベースにつなげる便利なサービスです。その分、「誰が、どのデータを読めるか」をデータベースの側で正しく決めておかないと、アプリの画面を通さずにデータを丸ごと読まれてしまいます。この記事では、Supabase の公式ドキュメントと実際に起きた事故をもとに、コードを読まなくても、管理画面とブラウザで確かめられる項目を順にまとめます。
Lovable や Claude Code などの AI ツールでアプリを作るとき、データの保存先として Supabase を使うことがよくあります。ログインの仕組みもデータベースもファイルの置き場所もそろっていて、画面から直接つなげるので、短い時間で動くものができあがります。
一方で、「Supabase で作ったアプリを、このまま公開して大丈夫か」という相談も増えています。Supabase は、正しく設定すれば安全に使えるサービスです。ただ、その「正しい設定」の中心にある RLS(Row Level Security。行ごとに、誰が読み書きできるかを決める設定)は、画面の見た目からは確かめられません。アプリの画面では自分のデータしか出ていなくても、裏側では全員のデータが読める状態になっていることがあります。
この記事は、Supabase を使ったアプリを公開しようとしている事業の担当者や、AI ツールで社内のアプリを作った方に向けて書いています。次のことを順にまとめます。
- Supabase で、データが漏れる仕組み
- 実際に起きた事故
- 管理画面で確かめる項目
- ブラウザで確かめる項目
- 鍵(API キー)で確かめる項目
- ファイルの置き場所とログインの設定で確かめる項目
- 自分で確かめられないこと
この記事の内容は、2026年11月6日時点の Supabase の公式ドキュメントにもとづいています。管理画面の表示は変わることがあるので、見つからないときは公式ドキュメントで最新の場所を確かめてください。
Supabase で、データが漏れる仕組み
ふつうの Web アプリでは、画面とデータベースの間にサーバーのプログラムがあり、「この人は、このデータを見てよいか」をそこで判断します。Supabase では、画面から直接データベースにつなぐ作りにできます。そのため、この判断をデータベースの側で行う必要があります。それが RLS です。
画面に置く鍵は、誰にでも見える
画面からデータベースにつなぐには、鍵(API キー)が必要です。この鍵は、ブラウザに送られる JavaScript の中に入るので、アプリを開いた人なら誰でも見られます。
Supabase の公式ドキュメントでも、公開用の鍵(publishable key)は、ブラウザやスマートフォンのアプリに置いてよいと説明されています。この鍵でできることは、RLS で許した範囲に限られるからです(API keys)。
つまり、画面に置く鍵は、見られる前提です。安全かどうかは、鍵を隠せているかではなく、RLS が正しく入っているかで決まります。
RLS がないテーブルは、鍵を持つ人なら誰でも読める
RLS が入っていないテーブルは、公開用の鍵を持っている人なら、誰でも中身を読み書きできます。公開用の鍵は画面から誰でも取り出せるので、結果として「インターネット上の誰でも読める」状態になります。
公式ドキュメントでは、外から呼べる場所(exposed schema)にあるすべてのテーブルで RLS をオンにするよう書かれています(Row Level Security)。本番に出す前のチェックリストでも、1つ目の項目が「すべてのテーブルで RLS をオンにする」です(Production checklist)。
「RLS がオン」だけでは足りない
RLS には、オンかオフかのスイッチと、「誰が、どの行を読めるか」を決めるルール(ポリシー)の2つがあります。
RLS をオンにして、ルールを1つも作らないと、公開用の鍵からは何も読めなくなります(Row Level Security)。安全ではありますが、アプリの画面も動かなくなります。
ここでありがちなのが、「とりあえず動かすために、誰でも読めるルールを足す」直し方です。こうすると、RLS はオンのまま、実際には誰でも読める状態に戻ります。Supabase の Security Advisor(後で説明する点検の機能)にも、「誰でも読み書きできるルール」を見つける項目があります(Database Advisors)。
RLS がオンになっているかと、ルールの中身が正しいかは、別のこととして確かめる必要があります。
実際に起きた事故
AI で作ったアプリの1割で、RLS の設定が足りなかった
2025年3月、AI でアプリを作るサービス Lovable で作られた1,645件のアプリを調べたところ、170件(約10.3%)で、RLS の設定が足りずにデータを読める状態だったと報告されました。この問題は CVE-2025-48757 として登録されています(報告者の声明)。
報告者は、その後 Lovable に入った点検の機能が、ルールが「あるかどうか」だけを見ていて、「正しいかどうか」は見ていないとも指摘しています。前の節で書いた、「オンになっている」と「正しい」の違いです。
鍵が画面にあり、RLS がなかったために、数百万件の記録が読めた
2026年1月には、AI で作られた SNS「Moltbook」で、Supabase のデータベースが外から読み書きできる状態だったことが分かりました。セキュリティ会社 Wiz の調査では、画面の JavaScript に入っていた鍵で、データベースに読み書きできたとされています。RLS のルールがなかったためです(Wiz)。
Wiz によると、読めた記録は合わせて約475万件で、約150万件の認証用のトークンや、メールアドレス、利用者どうしのメッセージが含まれていました。投稿を書き換えることもできたとされています。運営者は連絡から数時間で直しましたが、それまでの間は、誰でも読める状態でした。
どちらの事故も、高度な攻撃は使われていません。ブラウザで画面を開き、そこにある鍵でデータベースに問い合わせただけです。
管理画面で確かめる項目
ここからは、確かめ方を順に書きます。管理画面は、Supabase のプロジェクトの持ち主のアカウントで開いてください。
① Security Advisor で、赤い指摘(ERROR)がないか
Supabase には、データベースの設定を自動で点検する Security Advisor という機能があります。プロジェクトの管理画面の「Advisors」の中にあります(Database Advisors)。本番に出す前のチェックリストでも、「いつでも Security Advisor を実行して問題を見つける」よう書かれています(Production checklist)。
指摘は、ERROR、WARN、INFO の3段階で出ます。特に次の ERROR が出ていたら、公開を止めて直してください。
| 指摘の名前 | 意味 |
|---|---|
| rls_disabled_in_public | RLS がオフで、誰でも読めるテーブルがある |
| security_definer_view | RLS を通らずに読める「ビュー」がある |
| sensitive_columns_exposed | 個人情報などの大事な列が、誰でも読める |
| auth_users_exposed | 利用者の情報が、ビューを通して見えている |
| rls_references_user_metadata | ルールが、利用者が自分で書き換えられる情報をもとにしている |
WARN の中では、permissive_rls_policy(誰でも読み書きできるルール)と、public_bucket_allows_listing(ファイルの一覧を誰でも見られる置き場所)に注意してください。
公式ドキュメントにも書かれているとおり、指摘の中には、わざとそうしているものもあります(たとえば、誰でも見てよいお知らせのテーブル)。指摘が出たら、「このデータは、本当に誰でも見てよいか」を1つずつ判断します。
② すべてのテーブルで、RLS がオンになっているか
Security Advisor とは別に、テーブルの一覧でも RLS の状態を確かめます。本番前のチェックリストでは、管理画面の「Database」→「Tables」で確かめるよう書かれています(Production checklist)。
公式ドキュメントでは、新しく作るテーブルで RLS を自動でオンにするための仕組み(イベント トリガー)が別に紹介されています(Row Level Security)。作り方によっては、オフのままテーブルができることがあるということです。AI ツールがテーブルを作った場合も含めて、1つずつ見てください。
③ ルールの中身が、「誰でも」になっていないか
RLS がオンのテーブルでも、ルールの中身が「誰でも読める」になっていれば意味がありません。管理画面でテーブルを開くと、そのテーブルのルールを確かめられます。見つからないときは、作った人に、テーブルごとのルールの一覧を出してもらってください。
コードを読まなくても、ルールの名前と、対象の操作(読む、作る、直す、消す)と、対象の人(ログインしていない人、ログインした人)は分かります。次のような組み合わせがあれば、意図したものかを作った人に確かめてください。
- ログインしていない人(anon)が、読める・書けるルール
- 「ログインした人なら誰でも」すべての行を読めるルール(本人のデータだけに絞っていない)
- 消す・直すの操作が、誰にでも許されているルール
④ 「ビュー」が、RLS を通らずに読めていないか
ビューは、いくつかのテーブルを組み合わせて見せる仕組みです。公式ドキュメントによると、ビューはふつう、RLS を通らずに読める作りで作られます。もとのテーブルの RLS に従わせるには、security_invoker = true という設定が必要です(Row Level Security)。
テーブルの RLS を正しく設定していても、ビューから全員のデータが読めてしまうことがあります。①の security_definer_view の指摘が、これにあたります。
ブラウザで確かめる項目
管理画面の点検は、設定の「抜け」を見つけるものです。ルールが意図どおりに働いているかは、実際に使って確かめるのが確実です。
⑤ ログインしない状態で、データが見えないか
ブラウザのシークレット ウィンドウでアプリを開き、ログインせずに、データの一覧や詳細の画面の URL を直接開きます。ログインした人向けのデータが表示されたら、RLS が足りていません。
⑥ 別のアカウントで、他人のデータが見えないか
テスト用のアカウントを2つ作ります。片方で作ったデータの画面の URL を、もう片方のアカウントで開きます。URL の末尾の番号や ID を変えて開くのも試します。
他人のデータが見えたら、「本人のデータだけ」というルールが抜けています。お客様に使ってもらうサービスなら、お客様どうしのデータが見える状態なので、最優先で直します。
⑦ 画面で見えないだけで、データは届いていないか
画面には自分のデータしか表示されていなくても、裏側では全員のデータを受け取っていて、画面で絞っているだけのことがあります。
ブラウザの開発者ツール(Chrome なら F12 キー)の「ネットワーク」を開いてから、一覧の画面を読み込みます。Supabase への通信(URL に supabase.co を含むもの)を選び、「レスポンス」に他人のデータが含まれていないかを見ます。含まれていれば、画面で隠しているだけで、データは誰でも取り出せます。
鍵(API キー)で確かめる項目
⑧ 画面の側に、秘密の鍵が入っていないか
Supabase の鍵には、画面に置いてよい公開用の鍵と、画面に置いてはいけない秘密の鍵があります。秘密の鍵は RLS を無視して、すべてのデータを読み書きできます(API keys)。
| 鍵の種類 | 新しい名前 | 以前の名前 | 画面に置いてよいか |
|---|---|---|---|
| 公開用 | publishable key(sb_publishable_ で始まる) | anon key | よい(RLS の範囲だけ使える) |
| 秘密 | secret key(sb_secret_ で始まる) | service_role key | だめ(RLS を無視できる) |
ブラウザの開発者ツールの「ソース」で、sb_secret_ や service_role の文字を検索します。見つかったら、その鍵はすでに漏れたものと考えて、管理画面で新しい鍵に替え、古い鍵を無効にします。
公式ドキュメントによると、新しい秘密の鍵は、ブラウザから使われたことを検知すると、通信を断る仕組みになっています。ただし、これで安全になるわけではありません。鍵そのものはブラウザ以外の道具から使えるので、漏れた鍵はすぐに替えるよう書かれています(API keys)。
⑨ 以前の鍵(anon・service_role)から、移る計画があるか
Supabase は、以前の鍵(anon と service_role)を2026年末までに廃止すると発表しています(API keys)。以前の鍵は、新しい鍵と並べて使え、管理画面の「Settings」→「API Keys」で無効にするまで動きます。
以前の鍵を使っているアプリは、新しい鍵に替える作業が必要です。いつ、誰が替えるかを決めておいてください。
⑩ 鍵を書いたファイルが、GitHub に上がっていないか
秘密の鍵は、ふつう .env という名前のファイルに書きます。このファイルが GitHub などに上がっていると、そこから鍵が漏れます。リポジトリを開いて、.env という名前のファイルがないかを見てください。一度でも上げていれば、消しても履歴に残っています。その場合は、鍵を替えてください。
ファイルの置き場所とログインの設定で確かめる項目
⑪ ファイルの置き場所(バケット)が、意図せず「公開」になっていないか
Supabase の Storage では、ファイルの置き場所(バケット)ごとに、公開と非公開を選べます。公式ドキュメントによると、公開のバケットは、ファイルの URL を知っている人なら誰でも取り出せます。非公開のバケットは、RLS のルールで許された人だけが取り出せます。バケットは、作るときの初期設定では非公開です(Storage Buckets)。
商品の画像のように誰に見られてもよいものは、公開で問題ありません。請求書、本人確認の書類、社内の資料などが公開のバケットに入っていないかを確かめてください。
⑫ ログインまわりの設定が、本番向けになっているか
本番前のチェックリストでは、ログインまわりについて次の項目が挙がっています(Production checklist)。
- 登録のときに、メールアドレスの確認をオンにする
- テスト用に入れた電話番号を消す
- ワンタイムパスワードの有効期限を1時間(3600秒)以下にする
- 認証のメールを、自社のメールサーバー(SMTP)から送る
あわせて、登録やログインの画面に CAPTCHA(ロボットかどうかを確かめる仕組み)を入れることや、ログインの回数の制限を見直すことも、本番に出す前の手順に書かれています(Production Checklist)。
⑬ Supabase のアカウントそのものが守られているか
アプリの設定が正しくても、Supabase の管理画面に入られれば、すべてのデータを見られます。チェックリストでは、次の2つが挙がっています(Production checklist)。
- Supabase のアカウントに、多要素認証(MFA)を設定する
- 組織の持ち主(Owner)を2人以上にする。1人に連絡がつかなくなっても、管理できるようにするため
個人のアカウントで作ったプロジェクトを、そのまま会社のサービスに使っている場合は、会社の組織に移すことも考えてください。
自分で確かめられないこと
ここまでの13項目は、コードを読まなくても確かめられます。ただし、次のことは、作りを読める人でないと判断できません。
ルールが、すべての場面で正しく働くか
⑤と⑥は、自分が思いついた場面でしか試せません。公式ドキュメントでは、ルールをテストのコードで確かめる方法が紹介されていて、「テストが通るまで、ルールが意図どおりに働いているかは分からない」と書かれています(Row Level Security)。お金や個人情報を扱うアプリなら、このテストを作ってもらうことをおすすめします。
サーバー側の処理が、秘密の鍵を正しく使っているか
サーバー側の処理で秘密の鍵を使うと、RLS を通らずにデータを扱えます(Row Level Security)。その処理の中で「この人は、このデータを扱ってよいか」を確かめているかは、コードを読まないと分かりません。
利用者が増えたときに、どうなるか
RLS のルールの書き方によっては、データが増えると画面が遅くなることがあります。公式ドキュメントにも、RLS の速さについての別のページがあります(RLS Performance)。
これらは、AI ツールに「安全にして」と頼むだけでは確かめきれない部分です。公開する前に、一度エンジニアに見てもらうと安心です。
まとめ:公開前に確かめる13項目
最後に、この記事の項目を1つの表にまとめます。
| 場所 | 確かめること |
|---|---|
| 管理画面 | ① Security Advisor に ERROR がない |
| 管理画面 | ② すべてのテーブルで RLS がオン |
| 管理画面 | ③ ルールの中身が「誰でも」になっていない |
| 管理画面 | ④ ビューが RLS を通らずに読めない |
| ブラウザ | ⑤ ログインしないと、データが見えない |
| ブラウザ | ⑥ 別のアカウントで、他人のデータが見えない |
| ブラウザ | ⑦ 通信の中身に、他人のデータが入っていない |
| 鍵 | ⑧ 画面の側に秘密の鍵がない |
| 鍵 | ⑨ 以前の鍵から新しい鍵に移る計画がある |
| 鍵 | ⑩ 鍵を書いたファイルが GitHub に上がっていない |
| ファイル | ⑪ 大事なファイルが公開のバケットにない |
| ログイン | ⑫ メールの確認・有効期限・CAPTCHA などが本番向け |
| アカウント | ⑬ 多要素認証と、2人以上の持ち主 |
Supabase に限らない、AI で作ったアプリ全体の注意点は、「バイブコーディングのデメリットとセキュリティ:公開前に確かめる10項目」にまとめています。Claude Code を会社で使うときの設定は、「Claude Code を会社で安全に使う」をご覧ください。
よくある質問
公開用の鍵(publishable key・anon key)が、画面から見えても大丈夫ですか?
すべてのテーブルで RLS がオンになっていて、ルールが正しければ大丈夫です。公開用の鍵は、もともと画面に置く前提の鍵です。画面に置いてはいけないのは、秘密の鍵(secret key・service_role key)のほうです。
RLS をオンにしたら、アプリが動かなくなりました。
RLS をオンにして、ルールを作っていないと、公開用の鍵からは何も読めなくなります。動かすためには、「誰が、どの行を読めるか」のルールを作る必要があります。このとき、「誰でも読める」ルールで済ませると、オフにしたのと同じになるので注意してください。
Security Advisor で指摘が出なければ、安全ですか?
Security Advisor で見つかるのは、設定の「抜け」です。ルールの中身が、アプリの使われ方に合っているかまでは判断できません。⑤〜⑦のように、実際に別のアカウントで試すことと組み合わせてください。
AI ツールに「セキュリティを確認して」と頼めば十分ですか?
AI ツールは、頼まれた範囲を確かめます。ただし、どのデータを誰に見せてよいかは、事業の判断です。AI ツールは、その判断の材料を持っていません。どのテーブルを誰が読めるべきかを先に決めて、それに合っているかを確かめさせると、抜けが減ります。
以前の鍵(anon・service_role)は、いつまで使えますか?
Supabase は、2026年末までに廃止すると発表しています。新しい鍵(publishable・secret)と並べて使えるので、先に新しい鍵を作り、アプリを切り替えてから、以前の鍵を無効にする順番で進めます。
Firebase を使っている場合も、同じですか?
考え方は同じです。Firebase では、RLS にあたるものを「セキュリティ ルール」と呼びます。誰でも読み書きできるルールのまま公開していないかを確かめてください。管理画面の場所や指摘の名前は違うので、Firebase の公式ドキュメントで確かめてください。
NEWSLETTER