9個に1個のアプリがSupabaseキーを公開:流出の仕組みを徹底解説

BBetter Stack
Computing/SoftwareSmall Business/StartupsInternet Technology

Transcript

00:00:00今月発表されたレポートによると、約2万件の個人開発アプリを調査した結果、9つに1つの割合で
00:00:04フロントエンドのコード内にSupabaseの認証情報が露出していることが判明しました。
00:00:08これはサーバーのログや非公開リポジトリの話ではありません。
00:00:11訪問者がダウンロードするJavaScriptの中に、そのまま含まれているのです。
00:00:14重要なのは、ハッキングされたのではなく、不注意で機密情報を公開してしまったという点です。
00:00:18誤解のないように言うと、一部のキーは公開されることを前提としています。
00:00:21問題はそのプロセスにあります。同じミスによって、ブラウザに決して含めてはいけないはずの
00:00:25機密キーまで公開されてしまう可能性があるからです。
00:00:27私たちは常に新しい動画を配信しています。
00:00:28ぜひチャンネル登録をお願いします。
00:00:35ここで、多くの人が陥りやすい単純な事実をお話ししましょう。
00:00:38誰もが分かっているつもりでも、急いでいるとつい見落としてしまうことです。
00:00:41環境変数を「public」としてマークすると、ビルドツールはそれをブラウザ用と見なし、
00:00:46クライアント側のバンドルに追加します。
00:00:50Next.jsなら「Next.public」、Viteなら「Vite」、SvelteKitなら「public」を
00:00:56接頭辞に使うことでこの処理が行われます。
00:00:57「Next」は安全を保証するラベルではなく、文字通り「公開用」という配送ラベルなのです。
00:01:01それを踏まえた上で、Supabase特有の問題を見ていきましょう。
00:01:04「anon(匿名)」や「publishable」キーのように公開すべきキーがある一方で、
00:01:10「service_role」や「secret」キーのように秘匿すべきキーもあります。
00:01:12もしプライベートキーがブラウザに渡ってしまったら…どうなるか予想がつきますよね。
00:01:17その場合、行単位セキュリティー(RLS)も役に立ちません。
00:01:20Supabaseのドキュメントには、サービスキーはRLSをバイパスできると明記されています。
00:01:24つまり、そのキーがフロントエンドにあれば、設定したポリシーはすべて無意味になるのです。
00:01:29では、私のサンドボックスを使って、実際にどのようにこのミスが起きるかお見せします。
00:01:33まず、Next.jsで簡単なCRUDアプリを作成し、Supabaseを連携させました。
00:01:38これが私の.envファイルですが、ここに間違いがあります。
00:01:41「public」接頭辞が付いた変数にキーを入れてしまいました。
00:01:45このキーは公開用なので、表示されるのは想定通りです。
00:01:48本当の問題は、全く同じ「Next.public」というパスを使って、誤ってプライベートキーも公開できてしまうことです。
00:01:53「npm run build」を実行してビルドし、アプリを起動してみます。
00:01:59Chromeの画面です。
00:02:00CRUDアプリのデータベースに、適当なデータを素早く入力してみます。
00:02:05さて、コンパイルされたJavaScriptバンドルを開いて、キーを検索してみましょう。
00:02:10ありました。
00:02:12URLとキーが、ユーザーがブラウザに読み込んだファイルの中に
00:02:18そのまま居座っています。
00:02:19ここで注目してほしいのは、何が「起きていない」かです。
00:02:21不正アクセスされたわけではありません。
00:02:22私がただ見つけただけです。
00:02:24脆弱性を突いたわけでもありません。
00:02:25アプリが公開のインターネット上に自ら流した情報を読んだだけなのです。
00:02:29私に見えるなら、誰にでも見えます。
00:02:32デベロッパーツールを開き、JSファイルを調べて検索する。
00:02:35それだけでいいんです。
00:02:36「誰も見ないだろう」と思っているなら、ネット上にはこうした情報を探すのを
00:02:41仕事にしている人間やボットが溢れていることを忘れないでください。
00:02:44では、実際に効果のある修正方法を紹介します。
00:02:47ブラウザは自前のAPIのみを呼び出すようにすべきです。
00:02:50APIはサーバーサイドで動作します。
00:02:52プライベートキーを置くのはそこです。
00:02:54機密性の高い操作はAPIルートやサーバー関数に移動させてください。
00:02:58クライアントは自社エンドポイントを叩き、そこからSupabaseを呼び出します。その後、再ビルドしてバンドルを再確認します。
00:03:04バンドルからキーが消えていれば修正完了ですが、そこで満足してはいけません。
00:03:09他にもやるべきことはあります。
00:03:11ユーザーが触れるテーブルでは必ず行単位セキュリティー(RLS)を有効にし、
00:03:16ポリシーが意図通りに機能しているか確認してください。
00:03:18テストにも時間をかけましょう。
00:03:19ここは意外と軽視されがちな部分です。
00:03:21再発防止策についてですが、一度直しても、後で急いでいる時に
00:03:26また同じミスを繰り返してしまう人が多いのです。
00:03:28ガードレールを設置しましょう。まずはCIにシークレットスキャンを導入し、
00:03:34不適切な場所にキーがあればビルドが失敗するようにします。
00:03:36また、「next public」や「Vite」が付くものはデフォルトで公開情報として扱う
00:03:41プルリクエスト(PR)のルールを徹底してください。
00:03:42最後に、キーのローテーションを取り入れましょう。
00:03:43キーが露出した可能性がわずかでもあるなら、すぐに更新してください。
00:03:47数日間様子を見るよりも、その方がずっと安全です。
00:03:50今すぐ試せることをお伝えします。
00:03:52本番環境と同じようにアプリをビルドしてください。
00:03:55出力結果から「supabase」「JWT」「service_role」やトークンらしき文字列を検索しましょう。
00:04:01もしプライベートな情報が見つかったら、それは漏洩したものと考え、
00:04:05キーを更新してロジックをサーバーサイドへ移行してください。
00:04:08この動画で一つだけ覚えて帰るなら、これです。
00:04:11「バンドルに含まれているなら、それは公開情報である」
00:04:13それでは、また別の動画でお会いしましょう。

Key Takeaway

「クライアント側のバンドルに含まれる情報はすべて公開情報である」という原則を理解し、機密キーは必ずサーバーサイドで管理して露出を防ぐ必要があります。

Highlights

個人開発アプリの9つに1つという高い割合でSupabaseの認証情報が露出している現状

環境変数の接頭辞(Next.public等)を誤用することで、機密キーがJavaScriptバンドルに混入する仕組み

サービスロールキー(service_role)が露出すると、行単位セキュリティー(RLS)が完全に無効化される危険性

ブラウザ上のデベロッパーツールを使えば、誰でも簡単に公開されたキーを特定できてしまう事実

機密操作をサーバーサイド(APIルートやサーバー関数)へ移行することによる根本的な解決策

CIでのシークレットスキャン導入やキーの定期的なローテーションといった再発防止策の重要性

Timeline

衝撃的な調査結果と露出の現状

最近のレポートにより、約2万件のアプリのうち約11%でSupabaseの認証情報が露出していることが明らかになりました。これはサーバー攻撃によるものではなく、開発者がフロントエンドのコード内に誤ってキーを含めてしまったことが原因です。多くのケースでは、訪問者がダウンロードするJavaScriptファイルの中に機密情報がそのまま書き込まれています。一部のキーは公開前提ですが、不注意なプロセスが重大な漏洩を招いています。このセクションでは、ハッキングではなく設定ミスが最大の脅威であるという背景が説明されています。

環境変数の仕組みと「公開」の罠

開発者が急いで作業をしている際に見落としがちな環境変数の取り扱いについて詳しく解説しています。Next.jsの「Next.public」やViteの接頭辞は、ビルドツールに対してその変数をブラウザ用バンドルに含めるよう指示する配送ラベルのようなものです。これを「安全なラベル」と誤認してしまうことが、機密情報を公開インターネットへ流出させる直接的な原因となっています。開発ツールがどのように変数を処理するかを正しく理解することの重要性を強調しています。この単純なプレフィックスの付け間違いが、セキュリティ上の致命的な欠陥を生み出すのです。

Supabaseキーの種類とRLSの無効化

Supabaseにおける「anon」キーと「service_role」キーの決定的な違いについて説明が行われます。公開しても良いキーがある一方で、サービスロールキーは行単位セキュリティー(RLS)をバイパスできる強力な権限を持っています。もしこのプライベートキーがフロントエンドに漏洩すれば、設定したすべてのセキュリティポリシーは無意味になり、データベースが完全に無防備な状態となります。ドキュメントにも明記されているこの仕様を軽視することの危うさを警告しています。機密キーがブラウザに渡ることは、家の鍵を玄関に貼り出すのと同じくらい危険な行為です。

実演:ビルドされたファイルからのキー特定

実際のNext.jsアプリを用いたデモを通じて、どのようにキーが露出するかを視覚的に示しています。ビルドコマンドを実行し、生成されたJavaScriptバンドル内を検索するだけで、URLや機密キーが簡単に見つかる様子が再現されます。これは特別なハッキング技術を必要とせず、ブラウザのデベロッパーツールさえあれば誰にでも実行可能です。「誰も見ないだろう」という甘い考えは、常に情報を探しているボットや攻撃者が存在するネット上では通用しません。自ら情報を流しているという事実を直視し、脆弱性の本質を理解させる内容となっています。

修正方法とサーバーサイドへの移行

露出を防ぐための具体的かつ効果的な修正方法として、サーバーサイドロジックへの移行を推奨しています。機密性の高い操作はブラウザから直接行うのではなく、APIルートやサーバー関数を経由して実行すべきです。これにより、プライベートキーをサーバー上だけに留め、フロントエンドのバンドルから完全に排除することが可能になります。修正後は必ず再ビルドを行い、バンドル内からキーワードを検索して消去を確認する手順を解説しています。ブラウザには自社のエンドポイントのみを叩かせるという構造的な対策が不可欠です。

再発防止のためのガードレール設置

一度の修正で満足せず、継続的にセキュリティを維持するためのガードレールの設置方法を提案しています。CI(継続的インテグレーション)でのシークレットスキャン導入や、プルリクエスト時の厳格なルール作りが重要です。また、少しでも漏洩の疑いがある場合は、迷わずキーをローテーション(更新)する習慣を持つべきだと説いています。最後に、自分のアプリを本番環境と同様にビルドして自己チェックする具体的なアクションを促しています。「バンドルに含まれるなら公開情報である」という格言で締めくくられ、開発者の意識改革を求めています。

Community Posts

No posts yet. Be the first to write about this video!

Write about this video