💡

Supabase利用時に知っておきたい最低限のセキュリティ対策

に公開

概要

この記事では、私が新しいプロジェクトを作るたびに気をつけているsupabaseのセキュリティ設定・確認の3つのポイントを記載します。

先に結論

RLSをONにし、最小権限のポリシーを適用する
API Keys(anon / service_role)を安全に管理・ローテーションする
Security Checker(Security Advisor)で問題が発生していないか都度確認する

Vibe Codingなどコーディングを全てAIに任せる、といった便利な世の中ですが、下記のようにセキュリティの側面が軽視され、事故が起きてしまうのも事実です。
https://x.com/labelmake/status/1913155551963259148
https://x.com/soms277/status/1912988834087997488

ぜひ、最低限の確認を怠らずに素晴らしいプロダクトを世の中に送り出してください!

1.Row Level Security (RLS)

RLS は、テーブル単位ではなく「行(Row)」に対してアクセス制御ポリシーを適用する仕組みです。

  • テーブル単位の制御:従来の SQL 権限(GRANT/REVOKE)では、テーブル全体への SELECT/INSERT/UPDATE/DELETE 権限を付与・削除します。
  • 行単位の制御:RLS では、「どのユーザーがどの行にアクセスできるか」を柔軟に定義でき、同じテーブル内の他行へのアクセスを自動的にブロックします。

1-1.RLSの重要性

supabase では「匿名ユーザー向け」にクライアントから使う公開可能な API キーを anon key と呼びます。アプリのフロントエンドに埋め込まれて配布されるため、誰でも見ることができSupabase のパブリック API に認証なしでリクエスト可能です。

  • 全件取得・スクレイピング
    RLS 未設定の状態で anon key を使うと、SELECT * FROM public.example がそのまま通ってしまいます。たとえば、個人の購買履歴やチャットメッセージ、機密のユーザープロファイルをまるごと外部に持ち出される恐れがあります。
  • データ改ざん・削除
    INSERT/UPDATE/DELETE ポリシーを設定していないと、同じく anon key を持つ第三者が任意の行を書き換えたり、全レコードを削除してしまう事例も考えられます。運用中のサービスが一転して“消失事件”に発展しかねません。
  • サービス妨害(DoS)
    漏れた anon key を使って大量クエリや複雑な結合クエリを投げられると、データベース負荷が急増してサービス全体が低下・停止する可能性があります。

サービスの継続が危うくなるだけでなく、「個人情報の漏洩」など重大なインシデントにつながる恐れがあります。自身のプロジェクトからメールアドレスが流出したとき、どんな対応が求められるか、考えたくないですね。

1-2.具体的な設定

RLSはSupabase の Table Editor で作成すると自動でONになりますが、SQL で CREATE TABLE した場合は OFF のままです。必ず下記の形で設定しましょう。

-- 要注意!CREATE TABLE 後はデフォルト OFF。必ず実行すること
ALTER TABLE public.example
  ENABLE ROW LEVEL SECURITY;

また、RLS を有効にしても、そもそもテーブルに対する権限が残っていると意味がないので、public(=匿名ユーザー)からの全権限を剥奪しておきましょう。

-- 公開権限を剥奪(public ロールから SELECT などを削除)
REVOKE ALL ON public.example FROM public;

上記を行った上で、SELECT/INSERT/UPDATE/DELETEなど各メソッドに対して適切なRLSを適用しまよう。下記は、ログインユーザー本人しかSELECTできないポリシーの実装例です。

CREATE POLICY user_select_own
  ON public.example
  FOR SELECT
  USING (user_id = auth.uid());

これ以上の詳細な設定などは、下記を参照してもらうと良いと思います。
RLS をきちんと設定すれば、DB レイヤーで強固なアクセス制御が実現できます。まずは今回のサンプルをベースに、要件に応じてポリシーを拡張し、安全な運用を心がけましょう。
https://push.co.jp/articles/supabase-row-level-security-rls
https://supabase.com/docs/guides/database/postgres/row-level-security

2.API Keysの管理

Supabase では用途に応じて2種類のキーが発行されます。それぞれ権限と想定利用シーンが大きく異なるため、取り扱いを誤ると重大なセキュリティインシデントにつながります。

Key 役割 注意
anon key ブラウザ・モバイルなど、公開クライアント向けの匿名アクセス RLS(Row Level Security)が正しく設定されていれば公開してOK
service_role key バックエンド処理・バッチ/CLI向けの管理者権限アクセス RLSをバイパスする最強権限。絶対にフロントエンドへ渡さない

2-1.API Keysを適切に管理する重要性

  • service_role key 漏洩による権限の横取り
    サーバー専用の service_role key は全テーブルの読み書きを制御ポリシーを無視して実行できます。これが流出すると、悪意の第三者が全ユーザーデータを参照・改ざん・削除できてしまいます。
  • anon key の誤用によるデータ漏洩
    anon key は公開用ですが、RLS未設定・弱設定のまま公開すると、匿名アクセスで「全件SELECT」や「任意UPDATE」が可能に。機密情報や個人情報が丸裸になります。

特にservice_role keyは 「なんでもできてしまうkey」 です。最重要で注意して扱う必要があります。

2-2.API Keysの管理上で徹底すること

  • シークレット専用ストレージで一元管理
    • Vercel Environment Variables, GitHub Actionsなどの「暗号化された環境変数ストア」にのみ保管する。
    • リポジトリやコード中に平文で書かない。CI/CD パイプラインから直接参照し、開発マシンにキーを残さない。
  • キーのライフサイクルを明文化&定期ローテーション
    • どのキーが「開発」「ステージング」「本番」で使われているかを手順書にまとめる。
    • Supabase ダッシュボードの「Generate new secret」を使って、半年に一度など定期的に新しいキーへ更新。
  • ローテーション後は必ず動作確認を実施し、古いキーを速やかに無効化する。
    • コミット前の自動チェックを徹底
    • git-secrets や pre-commit フックで、平文キーやパターンにマッチする文字列が含まれていないかを検出。
    • GitHub の Secret Scanning に頼るだけでなく、開発者各自のローカル環境でも必ずチェックを通過させる。
    • 過去のコミット履歴にキーが残っていないかも、定期的にスキャンして漏洩リスクを断つ。​

詳細は下記などを確認してみてください
https://qiita.com/syukan3/items/8ec9b7288834e4c95f3b
https://supabase.com/docs/guides/api/api-keys

3. Security Checker

2024 年から Supabase Studio に搭載された Security Advisor についてです。この機能はsupabase側でセキュリティの設定不備などを自動検出し、我々に知らせてくれる強力な機能です。

ダッシュボード → Database › Security Advisor で自動実行され、

  • RLS 無効テーブル
  • ポリシーのない RLS テーブル
  • PUBLIC 権限付き関数
  • インデックス漏れの外部キー など

を “Critical” 〜 “OK” でリストアップしてくれます。​

3-1.使い方の流れ

  • 1.Security Advisor を開く
    Supabase Studio のサイドバーからDatabase → Security Advisor を選択。新規プロジェクトでは、初回は多数の警告が並びます。
  • 2.問題箇所を把握し、ドキュメントで対応策を確認
    各警告カードの右下にある “Fix guide” ボタンをクリックすると、Supabase ドキュメントの該当ページにジャンプします。
  • 3.修正後に再チェック
    設定を更新したら、Security Advisor の画面上部にある “Run Advisor” を押して再度スキャン。全てがOK になるまで繰り返しましょう。

とにかくここは最低限、変更を行った時は都度確認しましょう。

4.最後に

コーディング、システム開発の障壁が下がったことはとても良いことです。
可能性を持ってチャレンジする人は大好きですが、できる限りその方々か不幸な結末に陥らないように....。
色々書きましたが、個人的には漏洩してもダメージがない情報だけ扱う、できる限り不要な個人情報は持たない、などのそもそもの要件設計から見直すことも重要だと考えています。

参考になれば幸いです。

(追記)
https://x.com/yuno_miyako2/status/1913762957479322097
https://zenn.dev/soooms/articles/7fce58f1887120

別角度でこの辺も参考にしてみてね

Discussion