いつやるの?(正確なタイミング)
タイミングは明確で、譲れない:アプリを公開する、または実際のユーザーに渡す直前だ。 自分のパソコンで一人でテストしている間は何も起きない。だが、アプリが他人のデータを持ってネット上に出た瞬間、これらの鍵がなければすべてを晒すことになる。そしてAIは自分からはやってくれない(動かすことを考えていて、守ることは考えていない)ので、あなたが明示的に頼む必要がある。
鍵その1 · RLS(各自が自分のものだけを見る)
RLSがなければ、悪意あるユーザーはURLやリクエストのIDを1つ変えるだけで他人のデータを見られる。SupabaseやPostgreSQLを使うアプリで最もよくある脆弱性であり、最も簡単に悪用される。だからこれが鍵その1だ。
SupabaseをPostgreSQLで使っています。次のテーブルがあります:[あなたのテーブルとユーザー列を列挙、例:posts (user_id)、comments (post_id, user_id)]。 各ユーザーが自分のレコードだけを閲覧/編集/削除できるようにRow-Level Securityを設定してください。Supabaseの公式ベストプラクティスに従ってください: - すべてのテーブルでRLSを有効化する(ENABLE ROW LEVEL SECURITY)。 - SELECT、INSERT、UPDATE、DELETEごとに**別々の**ポリシーを作成する(FOR ALLは使わない)。 - パフォーマンスのために重要:ユーザー関数を (SELECT auth.uid()) のようにラップし、auth.uid() を裸で使わないこと。こうするとPostgresがクエリごとに1回だけ評価し、行ごとに評価しなくなります。 - ポリシーを authenticated ロールに限定する(TO authenticated)。public にはしない。匿名の訪問者がテーブルに触れられないようにするためです。 - ポリシーで user_metadata を**絶対に**使わない(ユーザーが改変できるため)。 - ポリシーで使う列(例:user_id)にインデックスを追加する。 - 忘れずに:UPDATE を機能させるには、SELECT のポリシーも必要です。 - SupabaseのSQL Editorにそのまま貼り付けられる完全なSQLをください。そして各ポリシーが何をするかを1行で説明してください。
auth.uid() を直接使うよう教える。だがそれだとPostgresが行ごとに1回ずつ評価してしまう——10万行のテーブルでは、5ミリ秒のクエリと5秒のクエリの差になる! 裏ワザ(Supabaseが文書化している):`(SELECT auth.uid())` と書くこと。こうすれば1回だけ評価される。だから上のプロンプトはこれを明示的に求めている。- アプリでテスト用ユーザーを2人作る。
- ユーザーAでログインしてレコードを1つ作る。
- ユーザーBでログインする:Aのレコードが見えてはいけない。
- SupabaseのSecurity Advisorを確認する:RLSを付け忘れたテーブルがあれば教えてくれる。
鍵その2 · CORS(誰があなたのAPIを呼べるか)
私の本番ドメイン(https://mi-app.com)と開発時の localhost だけがリクエストできるように、バックエンドのCORSを設定してください。 - 本番環境では許可オリジンに "*" を使わないこと。 - 実際に使うメソッド(例:GET、POST、PUT、DELETE)だけを許可する。 - 必要なヘッダーだけを許可する。 - 私のスタックに合わせて、それぞれをどこに置くか正確に説明してください:[あなたのフレームワーク/バックエンドを伝える]。
Access-Control-Allow-Origin: * を残すこと。ドアを開けっ放しにして「どうぞ、鍵は中に置いておきました」という看板を出すようなものだ。もしAIが「早く動かすため」にそう設定していたら、公開前に直そう。鍵その3 · Security Headers(ブラウザへの防御指示)
推奨されるセキュリティヘッダーを私のアプリに追加してください:Content-Security-Policy、X-Frame-Options、X-Content-Type-Options、Referrer-Policy、Strict-Transport-Security(HSTS)、Permissions-Policy。 - それぞれが何をするかを簡単な1行で説明してください。 - 私のフレームワークにそのまま使える設定をください:[使っているものを伝える、例:Next.js、Express]。 - Content-Security-Policy は何も壊さないように report-only モードで始めて、その後どう厳しくするか教えてください。 - 結果をどう検証するか教えてください。
習慣 · 公開のたびに見直す
- ユーザーデータを持つすべてのテーブルでRLS有効化(2アカウントでテスト済み)。
- CORSは自分のドメインに限定、認証情報付きで
*は絶対にしない。 - ヘッダーを設定し、securityheaders.com で評価A。
- 秘密情報(.env、APIキー)を絶対にGitHubに上げていない(シリーズのGitHubガイド参照)。
- SupabaseのSecurity Advisorを確認し、赤い警告が残っていない。