Supabaseのセキュリティ設定|公開前に確認するRLS・APIキーと「3条件の拒否テスト」

AI(Claude Code・Codex)で業務アプリを作り、ログインとデータ保存まで動いた。次に来るのが「このまま人に配って大丈夫なのか」という問いです。

結論から言います。公開前に確認するのは、ブラウザに置く鍵の種類テーブルごとの権限とRLS未ログイン・本人・別ユーザーの3条件での拒否テスト、この3つです。逆に言うと、「RLSをONにした」「SQLがエラーなく通った」は、まだ何も確認できていません。設定を書いたことと、利用者の立場で確かめたことは別です。順番に整理します。

Supabaseの安全設定とは何を決めることか Supabaseの安全設定とは、次の4つを決めることです。①Data API(HTTP経由でデータベースを読み書きするAPI)をどこまで公開するか ②テーブルごとにどの操作を許すか(GRANT) ③行単位で誰がどの行を読み書きできるか(RLS=行レベルセキュリティ) ④どの鍵をブラウザに置き、どの鍵をサーバー側だけに置くか。画面上で項目を隠す、フロント側で一覧を絞り込む、といった見た目の対処は、この4つのどれにも当たりません。

この記事は、みやっち🧑‍💻が2026年9月9日に、AI CrewでSupabaseを扱う回の教材を、Codexを使ってSupabase公式ドキュメントと1項目ずつ突き合わせた照合記録をもとにしています。点検したのは教材の記述と設定画面までで、特定のアプリの設定やアクセス試験は行っていません。そこで出てきたのが、Supabaseの安全性をめぐる説明のズレ5つと、公開前に押さえておきたい確認の要点でした。会員限定の教材そのものの中身には触れず、一般化できる部分だけを書きます。

「ブラウザからデータベースを操作できる構成そのものが危険」は一般化しすぎ

この言い方は、一般化しすぎです。Supabaseを使う構成で、ブラウザがデータベースに直接つながって任意のSQLを実行できるわけではありません。通常はData APIというHTTPのAPIを経由しており、DB管理者として全員に何でも許している状態とは別物です。

安全かどうかの境界は、構成の名前ではなく、定義ブロックに挙げた4つ(APIの公開範囲・テーブルごとの権限・行単位のアクセス制御・鍵の置き場所)で決まります。構成そのものを危険と切り捨てる説明も、構成を選んだだけで安全とみなす説明も、どちらもこの4つを飛ばしています。

もうひとつ、「Supabaseでは常にフロントエンドからデータベースへアクセスする」という説明も正確ではありません。必要がなければData APIは無効化できますし、サーバー側からデータベースへ接続する構成も取れます。何を公開するかは、こちらが選べます。

「RLSをONにした」「SQLが成功した」は安全の証拠にならない

ここが、いちばん誤解が起きやすいところです。SupabaseのSQL Editorでポリシーを作るSQLを実行すると、Success. No rows returned と表示されます。この表示の意味は、管理者権限(postgresロール)でそのSQLが通った、ということだけです。一般の利用者がアクセスしたときに正しく制限されるかどうかは、この表示からは一切わかりません。

RLSを有効にしたこと自体も同じです。有効化はスイッチであって、結果ではありません。どんなポリシーを書いたか、そのポリシーが一般利用者の認証状態でどう働くかは、別に確かめる必要があります。設定を書いた画面で成功したことと、利用者の立場で拒否されることは、まったく別の事実です。 この区別が、後半の拒否テストにつながります。

MCPを繋ぐかどうか、どのAIモデルを使うかは安全の根拠にならない

「MCPを繋がないと安全な設定はできない」という説明がありますが、根拠がありません。SQL Editor・CLI・マイグレーションのいずれでも、設定と検証はできます。MCPはAIから外部サービスを操作しやすくするための接続の仕組みであり、開発や点検の作業を助ける操作手段です。アプリ側の防御機構ではないので、繋いだから安全になる、繋いでいないから危険、という関係にはなりません。

同じ理由で、「このAIモデルなら厳重に設計できる」という語り方も避けてください。モデル名は安全性の根拠になりません。実際に効いているのは、書かれたポリシーと鍵の置き場所、そして自分で行った検証です。

公開前に確認する① ブラウザに置く鍵と、置いてはいけない鍵を分ける

「supabase anon key」で検索する人が多いのは、鍵が複数あって役割が分かりにくいからだと思います。ここは1行で押さえられます。

  • ブラウザ側に置いてよいのは publishableキー(以前のanonキー)だけ — 公開される前提の鍵です
  • secretキー(以前のservice_roleキー)とデータベースのパスワードは、公開側に置かない — これらはRLSを迂回できる強い鍵です

なお、従来のanonキー・service_roleキーはいまも使えますが、Supabaseは2026年末までに廃止する方針を公式ドキュメントで示しています。これから作るなら、publishableキーとsecretキーを使ってください。

注意したいのは、サーバー側で強い鍵を使う構成にしたとしても、それ自体は利用者の認証・認可にならないことです。「サーバー側だから安全」ではなく、誰がログインしているのか、その人に何を許すのかは、別に実装する必要があります。 鍵をコードに直書きせず環境変数に置く、リポジトリを非公開にするといった基本は、業務アプリをAIに作らせる始め方にまとめてあるので、作る工程からの続きとして読んでください。

公開前に確認する② RLSを有効にし、GRANTは必要な操作だけに絞る

APIで公開する対象のテーブルは、RLSを有効化します。そのうえで、GRANT(テーブルに対してどの操作を許すかの設定)を必要な範囲だけに絞ります。SELECT(読む)・INSERT(追加する)・UPDATE(変更する)・DELETE(消す)のそれぞれについて、誰に許すのかを決めてください。全部まとめて許可するのは避けてください。

教材の設計の考え方のうち、点検で妥当と判断できたのは次の3点でした。

  1. 認証と認可を分けて考える — 認証は「誰か」を確かめること、認可は「何をしてよいか」を決めること。別の話です
  2. 「ログイン済み」という条件だけでは、利用者どうしの分離になりません — 全員がログインしていれば全員の行が見える状態になりかねません。本人の行だけを読み書きさせるポリシーが要ります
  3. 親子関係のあるデータは、所有者と操作者の一致を確認する — 親テーブルの所有者と、いま操作している人が一致するかを WITH CHECK で確かめる方向です

公開前に確認する③ 未ログイン・本人・別ユーザーの3条件で拒否テストをする

ここがこの記事の山場です。設定を書き終えたら、利用者の立場でAPIを呼んで、拒否されることを自分の目で確かめます。 管理者権限のSQL Editorで成功しただけで完了にしないでください。

確かめるのは、次の3条件です。

条件誰として試すか期待する結果
①未ログインログインしていない状態他人のデータが一覧・取得できない
②本人自分のアカウント自分のデータは正常に読み書きできる
③別ユーザー別アカウント他人のデータを取得・変更・削除できない

この3条件に対して、一覧・取得・変更・削除の操作をそれぞれ試します。加えて、他人の会話IDやレコードIDを指定して、そこへデータを差し込めないことまで確かめてください。 読む側だけを塞いで、書き込む側が空いたままになる抜けも起こり得ます。

そして忘れてはいけないのが、②の本人の操作が正常に成功することを同時に確認することです。締めすぎて自分のアプリが使えなくなる、という逆方向の事故も起こり得ます。拒否と許可はセットで確かめます。

この3条件を確かめておけば、「動いたけれど配っていいのか分からない」状態から、どこまでは確かめてあり、どこからは未確認なのかを説明できる状態に進めます。判断材料を自分で作れる、というのがこのテストの価値です。

それでもRLSだけでは防げない範囲が残る

正直に書きます。ここまでをやっても「これで万全」にはなりません。

  • ビュー・RPC(データベース側に用意する関数)は個別に点検が必要 — ビューは初期設定のままだと作成者(通常は管理者のpostgresロール)の権限で動き、元のテーブルのRLSを通りません。関数も SECURITY DEFINER で作ると作成者の権限で動くため、RLSの想定を越えて動くことがあります
  • ストレージ(ファイル置き場)にも別途アクセス制御が要る — 自分のテーブルに書いたRLSはファイルまで守ってくれません。ファイルには storage.objects に専用のポリシーを書く必要があり、公開(public)設定のバケットに置いたファイルは誰でも取得できます
  • RLSは、過剰なアクセスの制限(レート制限)やあらゆる脆弱性への対策ではない — 役割が違います

そして、ここから先は技術設定だけの話ではなくなります。顧客の個人情報を扱うなら、どこまでをアプリに預けてよいかは、自社の社内規定・お客様との契約・利用しているサービスの規約で結論が変わります。人と契約の側の線引きはAIに個人情報はどこまで入力していいかに分けて書いているので、技術設定とセットで考えてください。公開する場所そのものの選び方はVercelとCloudflareの違いが参考になります。

公開前の確認に「これで終わり」という地点はありません。まずは3つの確認から始めて、扱うデータが重くなるほど点検の範囲を広げてください。 判断に迷う箇所は、情報システム担当や弁護士などの専門家に確認することをおすすめします。本記事は一般的な考え方の整理であり、法的助言ではありません。

「動いた」の先を、自分で確かめられるようにする

ここまで読んで、「けっこう考えることがある」と感じた方もいると思います。実際そのとおりで、だからこそ、作る前にどんなデータを誰に見せるのかを決めておくほど、公開前の確認が楽になります。 AI開発の要件定義の段階で「誰が使い、誰にどのデータを見せるのか」まで決めておけば、それがそのままRLSのポリシーの設計図になります。

そのうえで、この確認作業は外注先や誰かに丸投げしにくい性質を持っています。何を見せてよくて何を見せてはいけないかは、その事業のことを一番よく知っている人にしか決められないからです。Claude Code・Codexのような実行型のAIエージェントを自分で動かせると、ポリシーを書く、テスト用のアカウントで実際に試す、結果を見て直す、というやり取りを自分のペースで回せます。自分の事業のルールを、自分でアプリの設定に落とし込める——これは、既製のサービスを契約して使う立場のままでは手に入らない状態です。

とはいえ、SupabaseのRLSも鍵の管理も、一人で最初から正解にたどり着くのは大変な領域です。AI Crewでは、AIエージェントで自分専用の業務アプリを作り、公開するところまでを一緒に進めています。まず無料セミナーでお会いしましょう。

関連記事

「AI Crew」は株式会社AI Orchestraの登録商標(登録第6942947号)です。