メインコンテンツへスキップ
データベースに鍵をかける(RLS)
レッスン 3 / 15|10分で読めます

データベースに鍵をかける(RLS)

テーブルは作った瞬間、全世界公開。Supabaseの行レベルセキュリティ(RLS)を有効にし、鍵がかかったことを自分でテストする。

前回の宿題のような一文を、もう一度書きます。

データベースのテーブルは、作った直後は守られていない。

今回は、この開いたドアに自分の手で鍵をかけます。

対象はSupabase(Vibe Coding実装編で使ったデータベース)ですが、考え方はFirebaseなど他のサービスでも同じです。名前が「セキュリティルール」に変わるだけで、「初期状態は開いている。閉め方を知っているかどうか」という構図は変わりません。

  • RLSって、結局なにをしてくれるの?
  • 有効にすると、なぜ自分のアプリまで動かなくなるの?
  • 鍵がかかったことは、どうやって確かめるの?

今日はこの3つに答えます。

RLSは「行ごとの受付係」

RLS(Row Level Security、行レベルセキュリティ)は、データベースの行ひとつひとつに受付係を立てる仕組みです。

病院の受付を思い浮かべてください。診察券を出すと、受付係はその人のカルテだけを出してきます。「全患者のカルテを全部ください」と言っても、渡しません。誰が来たかを確認して、その人に見せてよい分だけを返す。これが受付係の仕事です。

RLSが無効なテーブルは、受付係のいない棚です。来た人が自由に棚を開けられます。

RLSを有効にして「ポリシー」という規則を書くと、受付係が立ちます。規則の例はこうです。

  • この行は、作った本人だけが読める
  • この行は、ログイン済みの人なら誰でも読めるが、書き換えは本人だけ
  • この行は、誰でも読める(公開データ)

注意

RLSを有効にしただけでは、まだ何も許可されていない

RLSを有効化した直後のテーブルは「全部拒否」になります。アプリが急にデータを読めなくなったら、それは壊れたのではなく、受付係が立ったのに規則をまだ渡していない状態です。ここで慌ててRLSをオフに戻すのが、いちばん危険な逆走です。戻すのではなく、規則(ポリシー)を書きます。

手を動かす: 鍵をかける3ステップ

自分のSupabaseプロジェクトで、次の3ステップをやってみます。SQLはAIに書かせて構いません。ただし、何を頼んでいるのかは自分で分かって頼みます。

ステップ1: 現状を確認する

Supabaseのダッシュボードを開き、Table Editorで各テーブルを見ます。RLSが無効なテーブルには、「RLS disabled」という赤い警告が表示されます。

まず全テーブルについて、この警告が出ていないかを見る。これだけで、前回のCVE-2025-48757型の事故(170件超)と同じ状態かどうかが分かります。

ステップ2: RLSを有効化し、ポリシーを書く

例として「メモアプリで、自分のメモは自分だけが読み書きできる」規則をかけます。

-- RLSを有効化(受付係を立てる)
alter table notes enable row level security;

-- 規則1: 自分の行だけ読める
create policy "read own notes"
on notes for select
using (auth.uid() = user_id);

-- 規則2: 自分の行だけ書ける
create policy "write own notes"
on notes for insert
with check (auth.uid() = user_id);

auth.uid() は「いまログインしている人のID」です。つまりこの規則は、行に記録された持ち主と、いま来ている人が同一のときだけ通す、と言っています。受付係が診察券を照合しているのと同じです。

AIに頼むときの指示文はこうなります。

「notesテーブルにRLSを有効化して、user_id列が自分のIDと一致する行だけをselect/insert/update/deleteできるポリシーを書いて。他人の行には一切アクセスできないこと」

ステップ3: 鍵がかかったことをテストする

ここがいちばん大事です。かけたつもり、で終わらせない。

いちばん確実なのは、ログインしていない状態(別ブラウザのシークレットウィンドウ)で自分のアプリを開き、他人のデータが見えないことを確かめること。さらに、テスト用アカウントを2つ作り、アカウントAで作ったデータがアカウントBから見えないことも確認します。

明日のアクション

今日中にやる3点セット

  1. Supabaseの全テーブルで「RLS disabled」警告が出ていないか確認する
  2. 警告が出たテーブルにRLSを有効化し、ポリシーをAIと一緒に書く
  3. シークレットウィンドウと別アカウントで「見えないこと」をテストする

「あとでやる」が通用しない理由

RLSは、あとで直せばいいものではありません。

第1回で見たとおり、公開されたURLは数時間で自動スキャンに見つかります。「まず動くものを公開して、セキュリティはあとで」の「あとで」が来る前に、ドアノブを回す機械のほうが先に来ます。

だから順番はこうです。

公開する前に、RLS。

これは標語ではなく、Supabase公式の本番移行チェックリストの最上段に書かれている要件です。

今日のまとめ

3行で振り返ります。

  • RLSは行ごとの受付係。有効化しただけでは全拒否で、ポリシー(規則)を書いてはじめて機能する
  • アプリが読めなくなってもRLSをオフに戻さない。規則を書くのが正解
  • 仕上げは必ず、「見えないことのテスト」。シークレットウィンドウと別アカウントで確かめる

セルフチェック

1. Supabaseで新しいテーブルを作った直後の状態として正しいのはどれ?

2. RLSを有効化した直後にアプリがデータを読めなくなった。正しい対応は?

次のレッスン

受付係は立ちました。次回は鍵そのものの話です。見られてもよい鍵(anon key)と絶対に見られてはいけない鍵(service_role key)の違い、そして環境変数という「サーバー側の金庫」の使い方を整理します。

参考・出典