蒼井凪
開発2026-06-04

Supabase の RLS 無効化は本当に危険か?anon key の露出リスクと現実的な対処フロー

Supabaseからセキュリティ警告メールが来た。RLSを無効にした状態でNEXT_PUBLICにanon keyを置くと何が起きるか。

Supabaseからメールが届いた。件名は「Your project has security issues」。開いたら「Row Level Security (RLS) が無効になっているテーブルがあります」という警告だった。

警告の意味

RLS(Row Level Security)はPostgreSQLの行単位アクセス制御機能だ。Supabaseで有効にすると、テーブルへのアクセスに対してポリシーを設定でき、「このユーザーはこの行だけ読める」といった制御ができる。

RLSを無効にすると、テーブルへのアクセス制御はSupabaseのAPIキーのレベルだけに依存する。

anon key が NEXT_PUBLIC に置いてある場合の問題

Next.jsのフロントエンドから直接Supabaseにアクセスする構成では、NEXT_PUBLIC_SUPABASE_ANON_KEY という環境変数にanon keyを置くのが一般的だ。NEXT_PUBLIC_ プレフィックスがついた環境変数はブラウザに公開される。つまり、サイトにアクセスした人であれば誰でもanon keyを取得できる

Supabaseのanon keyは「匿名ユーザーとしてAPIを叩くためのキー」だ。これ自体は公開されることを想定して設計されている。問題はその組み合わせだ。

  • anon keyが公開されている(誰でも取得できる)
  • RLSが無効になっている(行レベルの制御がない)

この2つが重なると、anon keyを入手した人が service_role キーなしでテーブルのデータを自由に読み書きできる状態になる。

# anon keyだけあれば誰でもこれが動く
curl 'https://xxxxxxxxx.supabase.co/rest/v1/users?select=*' \
  -H "apikey: eyJxxxxxx" \
  -H "Authorization: Bearer eyJxxxxxx"

どんな場合に問題で、どんな場合に問題でないか

問題になるケース:

  • 本番サービスでユーザーデータやセンシティブなデータを保持している
  • 書き込みを想定していないデータに誰でも書ける状態
  • テーブルが実質公開状態になって困る内容を持っている

意図的にOKなケース:

  • 開発・実験用のプロジェクトで外部公開しない
  • テーブルの内容が本来パブリックなデータ(公開してよい情報のみ)
  • サーバーサイドのみでAPIを叩き、フロントにanon keyを置いていない

開発段階でRLSを後回しにしている場合、Supabaseは警告メールを送ってくる。警告メール自体は「危険な状態」を教えてくれているだけで、即座にデータが漏れているわけではない。ただし、そのプロジェクトをそのままデプロイして公開すると問題になる。

対処フロー

パターンA:フロントから直接Supabaseにアクセスしている場合

RLSを有効化し、ポリシーを設定する。最低限のポリシーは:

-- 認証済みユーザーは自分のデータだけ読める
CREATE POLICY "Users can read own data"
ON public.users
FOR SELECT
USING (auth.uid() = id);

ポリシーを設定せずにRLSだけ有効にすると、全アクセスが拒否されるので注意。

パターンB:サーバーサイドのみでアクセスしている場合

Next.jsのServer ComponentsやRoute Handlerからのみアクセスし、フロントにanon keyを置かない構成なら、RLS無効でも実害は小さい。フロントに NEXT_PUBLIC_ でキーを置かず、サーバーサイドの環境変数 + service_role キーで操作する。

// server-side only
import { createClient } from '@supabase/supabase-js'

const supabase = createClient(
  process.env.SUPABASE_URL!,
  process.env.SUPABASE_SERVICE_ROLE_KEY! // NEXT_PUBLIC_ なし
)

この場合、anon keyはブラウザに公開されない。

パターンC:開発専用で外部公開しない

ローカル開発や検証専用であれば、Supabaseの警告は無視して先に進んでよい。本番公開前に必ずRLSの設計を見直す。

まとめ

  • anon keyの公開 + RLS無効 = テーブルが事実上パブリック
  • anon keyはそもそも公開を想定した設計なので、問題はRLS無効の方にある
  • フロントから直接Supabaseにアクセスする構成ならRLSは必須
  • サーバーサイドのみでアクセスするなら NEXT_PUBLIC_ を使わず service_role キーで完結させる方が設計として明快

※ 本記事にはアフィリエイトリンクが含まれます。

開発 一覧へ