Supabase のシークレットキーがブラウザから見えていたら? 最初の1時間でやること
フロントエンドに service role キーやシークレットキーがあると、誰でもデータベースを自由に操作できます。無効化、差し替え、ログ確認、原因の修正という正しい順番を解説します。
6分で読めます
10分でできる Supabase チェックのとおりにアプリの JavaScript を service_role や sb_secret_ で検索したら、見つかってしまった。あるいは、誰かから「見つけました」とメールが届いた。どちらにしても、データベースのセキュリティルールをすべて無視できるキーが公開状態になっています。
AIで作ったアプリが抱えうる問題の中で最も深刻なもので、しかも珍しくありません。良い知らせは、正しい順番で進めれば修正は1時間ほどで終わることです。
このキーが特別な理由
Supabase はどのプロジェクトにも2種類のキーを用意しています。
| キー | 置くべき場所 | できること |
|---|---|---|
publishable key(sb_publishable_…)または従来の anon キー |
ブラウザ | Row Level Security のルールが許可する操作だけ |
secret key(sb_secret_…)または従来の service_role キー |
サーバーだけ | すべて。Row Level Security を完全に無視します |
シークレットキーがあれば、第三者はルールの抜け穴を探す必要すらありません。すべてのテーブルを読み、どの行でも書き換え、データを削除し、非公開のストレージからファイルをダウンロードできます。あなたのルールは、その人には一切適用されません。
0〜10分:漏れたのがどのキーかを確認する
Supabase のダッシュボードで Project Settings → API Keys を開き、ブラウザで見つけたものと比べます。
sb_secret_で始まるなら、新しいシークレットキーです。ほかに影響を与えず、そのキーだけを差し替えられます。eyJで始まる長いトークンなら、従来の service_role キーです。従来のキーは1本ずつ差し替えられないため、手順が異なります(後述)。
あわせて、キーがどこで使われていたか(どのファイルの、どの機能か)をメモしておきます。AIツールがこのキーをフロントエンドに入れるのは、たいてい公開キーで何かが失敗したときです。原因の多くは RLS のルール不足で、手っ取り早い回避策として RLS を無視するキーが使われたわけです。
10〜30分:キーを差し替える
新しいシークレットキー(sb_secret_)の場合
- API Keys で新しいシークレットキーを作成し、用途がわかる名前(例:
edge-functions)を付けます。 - サーバー側のコードが必要とする場所すべてに新しいキーを設定します。Edge Functions のシークレット、ホスティングの環境変数、バックグラウンドジョブなどです。
- 漏れたキーを削除します。そのキーを使ったリクエストは、その時点から失敗するようになります。
従来の service_role キーの場合
- まだなければ、API Keys のページで publishable key と secret key を作成します。
- フロントエンドの anon キーを publishable key に、サーバー側の service_role を secret key に置き換え、デプロイします。
- 同じページで従来の API キーを無効化します。これで anon と service_role の両方が同時に止まるため、手順2を先に済ませておく必要があります。見落としたクライアントがあっても再有効化できるので、この操作は元に戻せます。
Supabase は従来のキーをいずれ廃止する予定なので、遅かれ早かれ必要になる作業です。
30〜45分:フロントエンドからキーを完全になくす
キーを差し替えれば流出は止まりますが、そのキーに頼っていた処理は動かなくなります。ここで新しいシークレットキーをブラウザに戻してはいけません。処理をサーバー側に移します。
- Supabase の Edge Function:強い権限が必要だった操作(招待メールの送信、管理用テーブルへの書き込み、有料 API の呼び出しなど)を担当させます。Edge Functions はプロジェクトのシークレットキーを環境から読めるので、コードに貼り付ける必要はありません。
- または RLS のルール:その画面に必要な操作だけを正確に許可します。AIがシークレットキーに頼った理由が、「RLS は有効なのに、ログイン中のユーザー向けのルールがないテーブル」だったことはよくあります。正しいルールがあれば、シークレットキーは不要になります。
その後、ビルドされた JavaScript をもう一度 sb_secret_、service_role、新しいキーの先頭の数文字で検索します。ヒットがゼロになれば完了です。
45〜60分:公開されていた間に何が起きたかを確認する
キーが使われたかどうかを知るにはログが必要で、ログには保存期間があります。
- ダッシュボードの Logs で、公開されていた期間の API リクエストを確認します。異常な件数、アプリが読まないテーブルへのリクエスト、
select=*による一括取得、身に覚えのない削除などに注意してください。 - Auth → Users に見覚えのないアカウントがないか、ストレージにアップロードした覚えのないファイルがないかを確認します。
- データが改ざんされた疑いがあるなら、ほかの変更を加える前に、ご利用のプランにどのようなバックアップやポイントインタイムリカバリが含まれているかを確認してください。
Supabase のログ保存期間はプランによって異なり、短い場合もあります。来週ではなく、今日のうちに確認してください。
再発を防ぐために
AIツールは、プロジェクト内で一度見たやり方を繰り返します。次の習慣で二度目の流出を防げます。
- シークレットキーはサーバー側の環境変数だけに置き、フレームワークがブラウザに送る変数には入れないこと(Vite では
VITE_で始まる変数、Next.js ではNEXT_PUBLIC_で始まる変数はすべてバンドルに含まれます)。 - シークレットキーはサービスごとに1本ずつ、名前を付けて使い分けること。流出しても差し替えは1本で済みます。
- リリース前に毎回、ビルド結果を
sb_secret_とservice_roleで検索すること。数秒で終わります。 - エラーを消すためにAIがシークレットキーを提案してきたら、RLS のルールが足りていないサインだと考えること。
キー、ルール、ストレージ、認証まで含めてアプリ全体を確認してほしい場合は、無料の Security Check をご利用ください。外部から読み取り専用で確認し、最初に直すべき点をお伝えします。
SupabaseAPIキーAIで作ったアプリ
あわせて読みたい
記事一覧
アプリのセキュリティ
AIで作ったアプリ、データが漏れていませんか? 10分でできるSupabaseチェック
Lovable や Bolt と Supabase で作ったアプリは、誰でも読めるテーブルのまま公開されていることがよくあります。10分で確認する方法と、最初に直すべき点を解説します。
4分で読めます

ウェブサイト
お問い合わせフォームのメールが迷惑メールに入る理由と、SPF・DKIM・DMARC による解決法
サイトのフォームから届くメールが迷惑メールに入る、または届かない。原因の多くは内容ではなく送り方です。確認すべき点と、設定すべき3つの DNS レコードを解説します。
5分で読めます