supabase は何をしますか?
基本原則
1. Supabase は頻繁に変更されます — 実装する前に、変更ログと現在のドキュメントを確認してください。 Supabase の機能についてトレーニングデータに依存しないでください。関数シグネチャ、config.toml 設定、API 規則はバージョン間で変更される可能性があります。
まず、https://supabase.com/changelog.md(軽量なサマリーインデックス — 大量のデータではありません)を取得し、タスクに関連する breaking-change タグをスキャンし、該当するものについてはリンク先のページを参照してください。次に、以下のドキュメントアクセス方法を使用して、関連するトピックを調べてください。
2. 作業内容を確認してください。 修正を実装した後は、必ずテストクエリを実行して変更が機能することを確認してください。確認なしの修正は不完全です。
3. エラーから回復し、ループしないでください。 アプローチが 2〜3 回試行しても失敗した場合は、一旦止めて再考してください。別の方法を試すか、ドキュメントを確認するか、エラーをより注意深く調べるか、利用可能な場合は関連するログを確認してください。Supabase の問題は、同じコマンドを再試行しても常に解決するとは限らず、答えが常にログにあるとは限りませんが、先に進む前にログを確認する価値はよくあります。
4. Data API へのテーブルの公開: ユーザーの Data API 設定 によっては、新しく作成されたテーブルが Data (REST) API を介して自動的に公開されない場合があります。この場合、anon ロールと authenticated ロールに明示的にアクセス権を付与する必要があります。
これは RLS とは別のものであることに注意してください。RLS は、テーブルにアクセス可能になった後にどの 行 が表示されるかを制御するものであり、テーブルにアクセス可能かどうか自体を制御するものではありません。
ユーザーが SQL で作成したテーブルに予期せずアクセスできないと報告した場合、Data API 設定と、明示的な GRANT SQL によってロールにアクセス権が付与されているかどうかを確認してください。パブリック(anon/authenticated)アクセスを許可する場合は、常に RLS も有効にしてください。完全な設定ワークフローについては、「テーブルを Data API に公開する」を参照してください。
5. 公開スキーマでの RLS。
公開スキーマ(デフォルトで public を含む)内のすべてのテーブルで RLS を有効にしてください。Supabase では、anon/authenticated ロールがアクセス権を持つ場合、公開スキーマ内のテーブルは Data API を介して到達可能になる可能性があるため、これは重要です(「テーブルを Data API に公開する」を参照)。プライベートスキーマの場合は、多層防御として RLS を推奨します。RLS を有効にした後は、すべてのテーブルに同じ auth.uid() パターンをデフォルトで適用するのではなく、実際のアクセスモデルに一致するポリシーを作成してください。
6. セキュリティチェックリスト。 認証、RLS、ビュー、ストレージ、またはユーザーデータに触れる Supabase タスクに取り組む場合は、このチェックリストを実行してください。これらは、静かに脆弱性を生み出す Supabase 固有のセキュリティトラップです。
-
認証とセッションのセキュリティ
- JWT ベースの認可決定に
user_metadataクレームを絶対に使用しないでください。 Supabase では、raw_user_meta_dataはユーザーが編集可能であり、auth.jwt()に表示される可能性があるため、RLS ポリシーやその他の認可ロジックにとって安全ではありません。代わりに、認可データをraw_app_meta_data/app_metadataに保存してください。 - ユーザーを削除しても、既存のアクセストークンは無効になりません。 最初にサインアウトするかセッションを取り消し、機密性の高いアプリでは JWT の有効期限を短く保ち、厳格な保証が必要な場合は、機密性の高い操作で
session_idをauth.sessionsに対して検証してください。 - 認可に
app_metadataまたはauth.jwt()を使用する場合、JWT クレームはユーザーのトークンが更新されるまで常に最新であるとは限らないことに注意してください。
- JWT ベースの認可決定に
-
API キーとクライアントの露出
- パブリッククライアントで
service_roleキーやシークレットキーを絶対に公開しないでください。 フロントエンドコードでは、公開可能キーを優先してください。レガシーanonキーは互換性のためだけに使用されます。Next.js では、NEXT_PUBLIC_環境変数はすべてブラウザに送信されます。
- パブリッククライアントで
-
RLS、ビュー、および特権データベースコード
- ビューはデフォルトで RLS をバイパスします。 Postgres 15 以降では、
CREATE VIEW ... WITH (security_invoker = true)を使用してください。古いバージョンの Postgres では、anonロールとauthenticatedロールからのアクセスを取り消すか、公開されていないスキーマにビューを配置して保護してください。 - UPDATE には SELECT ポリシーが必要です。 Postgres RLS では、UPDATE は最初に行を SELECT する必要があります。SELECT ポリシーがない場合、アップデートは静かに 0 行を返します — エラーはなく、単に変更がありません。
auth.role()は非推奨です — 代わりにTO句を使用してください。 Supabase は、auth.role()の代わりに、ポリシーでターゲットロールを直接指定するためにTO authenticatedまたはTO anonを使用することを推奨しています。非推奨であることに加えて、auth.role() = 'authenticated'は、匿名サインインが有効な場合に静かに機能しなくなります。これは、匿名ユーザーがauthenticatedPostgres ロールを持ち、ユーザーが実際にサインインしているかどうかに関係なくチェックを通過するためです。-- 非推奨(使用しないでください) create policy "example" on table_name for select using ( auth.role() = 'authenticated' );TO authenticatedだけでは、認証はあっても認可はありません(BOLA / IDOR)。TO authenticatedを使用することは、ロールをチェックするだけです — ユーザーがどの行にアクセスできるかを制限するものではありません。正しいパターンは、TO authenticatedとUSING内の所有権述語を組み合わせることです:create policy "example" on table_name for select to authenticated using ( (select auth.uid()) = user_id );- UPDATE ポリシーには
USINGとWITH CHECKの両方が必要です。WITH CHECKがないと、ユーザーは行のuser_idを別のユーザーに再割り当てできます:create policy "example" on table_name for update to authenticated using ( (select auth.uid()) = user_id ) with check ( (select auth.uid()) = user_id ); SECURITY DEFINER関数は RLS をバイパスします。SECURITY DEFINER関数は、その作成者の権限(通常はbypassrlsを持つロール、例:postgres)で実行されます。権限エラーを解決するためにSECURITY DEFINERを決して追加しないでください。これは、根本的な原因を修正せずに静かにアクセス制御を削除します。SECURITY INVOKERを優先してください。public内のSECURITY DEFINER関数は、すべてのロールから呼び出し可能です。 Postgres は、新しい関数ごとにデフォルトでPUBLICにEXECUTEを許可するため、public内のSECURITY DEFINER関数は、追加の許可なしにanonおよびauthenticated(PUBLICから継承)から呼び出し可能な公開 API エンドポイントになります。SECURITY DEFINERが本当に必要な場合(例:内部ルックアップテーブルで RLS をバイパスする)、関数を公開されていないスキーマに保持し、関数本体に常にauth.uid()チェックを含め、変更後にsupabase db advisorsを実行してください。
- ビューはデフォルトで RLS をバイパスします。 Postgres 15 以降では、
-
ストレージアクセス制御
- ストレージの upsert には INSERT + SELECT + UPDATE が必要です。 INSERT のみを許可すると、新しいアップロードは可能ですが、ファイルの置換(upsert)は静かに失敗します。3 つすべてが必要です。
-
依存関係とサプライチェーンセキュリティ
- Supabase パッケージ(
supabase-js、@supabase/ssr、supabase-pyなど)をインストールするときは、常にパッケージバージョンを固定し、ロックファイルをコミットしてください。 完全なチェックリストについては、npm セキュリティガイド を参照してください。
- Supabase パッケージ(
上記でカバーされていないセキュリティ上の懸念事項については、Supabase プロダクトセキュリティインデックスを取得してください:https://supabase.com/docs/guides/security/product-security.md