はじめに
前回の動画では、脆弱性の基礎的なお話をしました。座学だけだと頭に入りづらいので、今回は実際に脆弱性のあるアプリを作り、私がハッキングしてみます。ローカル環境なので犯罪にはなりません。どういう危険性があるのかを体感していただければと思います。私が実演しますので、皆さんはやらなくて大丈夫です。
あわせて、どういうコードだから脆弱性があるのか、どう修正すれば防げるのかについても解説します。
題材:Todoアプリ
今回は Claude Code に作らせたTodoアプリを題材にします。Aliceという名前でログインし、Todoを追加・管理できる形にしています。今回説明したいのは環境変数(大事なキー)の扱いです。これをそのままフロントエンド(見た目の部分)に含めてしまうと、どこで見られてしまうのかを確認していきます。
開発者ツールで何が見えるのか
ブラウザの開発者ツールは F12 で開けます。これはどのサービスでも開けるもので、開発者コンソールと呼ばれます。アプリの見た目の部分(フロントで見える部分)は、すべて閲覧できます。
このように、HTMLの骨格やCSSの内容を見ることができます。すべてではありませんが、大抵は見られてしまいます。
ネットワークタブとJavaScriptファイル
今回のTodoアプリは、データベースに Supabase を使っています。Supabaseには service role key という非常に重要なAPIキーがあります。今回はあえて、これを露出させています。
どこで確認できるのかというと、ネットワークタブです。JavaScriptファイルを選択してページをリロードすると、いろいろな名前のファイルが読み込まれているのが分かります。あまり見たことがない方も多いかもしれませんが、これらはJavaScriptファイルです。
JavaScriptファイルには、たとえばTodoを追加するロジック、削除するロジック、ボタンを押したときの処理などが含まれます。Next.jsの Client Component で書いてしまうと、こうした処理が全部ネットワークタブから見えてしまいます。
service role key の露出
ソースから始まるファイルを開くと、Todoアプリの中身がほとんど書かれています。中を覆ってみると、SUPABASE_URL・ANON_KEY・SERVICE_ROLE_KEY が書かれており、sb_secret から始まるキーが露出してしまっています。
これは外部に流出してはいけないキーです。service role key が流出すると、データベースを何でもいじれてしまいます。データベースを削除することもでき、本当に何でもできてしまうキーです。したがって、絶対にクライアント側で露出してはいけません。
そもそも、この service role key は使わないほうがよいです。使わなくても実装できます。Supabaseを使う場合は、URL と anon key の2つだけで実行してほしいところです。
anon key と service role key の違い
URL と anon key は、クライアント側に露出することを前提に作られたキーとURLです。これらは見えていても問題ありません。Supabaseはそういう設計になっています。
一方で service role key は流出してはいけないので、ここに気をつける必要があります。
なぜ流出したのか
原因は、supabaseClient.ts というファイルにあります。Claude Code がこのファイルを作り、環境変数も使わずにキーをそのままハードコード(手書き)で埋め込んでいました。
なお、環境変数を使ったとしても、クライアント側で書いてしまえば露出するので意味がありません。
この service role key がどのファイルで使われたかが重要です。たとえば login-form などのファイルでimportされており、ファイルの先頭に use client と書かれています。これは Client Component である印で、その名のとおりクライアントですべて露出してしまうファイルです。そのため、supabaseClient.ts に書いたAPIキーもすべてブラウザに露出します。先ほどネットワークタブで見たとおり、露出してしまっていたわけです。
これは、AIを使ってアプリを作り始めた非エンジニアの方には、ほぼ絶対に気づけない脆弱性だと思います。今回はあえて脆弱性を含んだアプリを作らせたのでこうなっていますが、普通に作る分には、おそらくAIはこういうミスはしません。ただし、「アプリが動かないから何としても動かしてほしい」と強く指示すると、AIがやってはいけない操作を強引に行い、露出につながるケースもあります。十分に気をつけてください。
どうすればよかったのか
対策は次のとおりです。
- そもそも
service role keyを使わない(使わなくても実装できる) - もし使うのであれば、Client Component では使わず、Server Component や API(Route Handler)といったサーバー側で使う
Next.jsのベストプラクティスとして、Client Component はなるべく使わず、Server Component で実装するのが基本方針です。公式にもあるように、これはセキュリティ面で安全だからです。Next.jsではRoute Handlerを作ってAPIを書くこともできるので、そこで service role key を使う形にします。
ただし、API経由であっても攻撃を受ければ service role key は全権限を持ってしまい、RLSも完全に無視するため危険です。したがって、そもそもなるべく使わないのが基本です。優先度としては、service role key を使わずに anon key と URL だけで、サーバーサイドで実装するのがよいでしょう。
なお、anon key と URL だけで実装しても、RLSポリシーを設定しないとデータにアクセスされてしまうので、そこも注意してください。RLSポリシーについては、続く動画で扱います。
最後に
もしかすると、バイブコーディングで作ったアプリでも、この service role key が露出してしまっている可能性があります。一度確認してみると発見があるかもしれません(おすすめはしません)。
そして、絶対に悪用はしないでください。キーが漏れているからといって悪用すると犯罪になります。もし誰かのキーの露出を見つけたら、DMなどで「露出していますよ」と教えてあげると親切です。