本文へスキップ

Supabase public bucket:誰がファイルを読めるか

Supabase

Markdownで表示Claudeで開くChatGPTで開くPerplexityで開く

質問もコピーされます。チャットが空で開いた場合は貼り付けてください。

TL;DR

公開バケットは、URLを知っている誰にでも、キーもログインもなしでバケット内のすべてのファイルを提供します。ダウンロードでは、あなたのstorageポリシーは参照されません。私のローカルスタックでは、同じテストファイルが、公開バケットでは内容付きの200を、非公開バケットでは400を返しました。アップロード、削除、移動は、引き続きポリシーを通ります。公開バケットはアバターや記事の画像のように本来公開されるファイルに使い、それ以外は非公開バケットと署名付きURLを使ってください。

私の無料のSupabaseセキュリティチェッカーには、バケットに関するルールが2つあります。「公開されたストレージバケット」は、公開バケットを一覧にして、それぞれが本当に公開でよいかを確認できるようにします。「アップロード制限のない公開バケット」は、サイズやファイル形式の制限がない公開バケットを指摘します。ここでは、公開フラグが実際に何を変えるのかを見ます。

Supabaseの公開バケットとは何?

Supabaseのバケットガイドは、2つのアクセスモデルを定義しています。非公開バケットでは、ダウンロードを含むすべての操作がstorage.objectsのRLSポリシーを通ります。ファイルは、ユーザーのトークンか、期限付きの署名付きURLで読みます。公開バケットでは、ファイルの取得と配信がアクセス制御を迂回するため、URLを知っていれば誰でもファイルを読めます。アップロード、削除、移動、コピーには、引き続きアクセス制御が適用されます。

バケットはデフォルトで非公開です。ダッシュボードでチェックボックスを入れるか、public: trueで作成すると公開になります。画像が表示されないときの手っ取り早い方法として、よく使われます。

私のテストで各バケットは何を返した?

ローカルのSupabaseスタック(CLI 2.109.1)で、公開バケットと非公開バケットを1つずつ作り、同じ小さなテキストファイルをsecret keyで両方にアップロードしました。そのあと、リンクを知っただけの第三者のように、キーなしでリクエストしました。

同じファイルを、キーなしでリクエスト。ローカルのSupabase Storage、公開と非公開のバケット各1つ。公開バケット:リクエスト、キーなし → 公開バケット → 200、ファイル送信、非公開バケット:リクエスト、キーなし → 非公開バケット → 400、見つからない。
ローカルのSupabaseスタックでの私の再現、2026年10月23日。
2026/invoice-001.txtへのリクエスト 公開バケット 非公開バケット
/storage/v1/object/public/…、キーなし 200、ファイルの内容 400、“Bucket not found”
/storage/v1/object/authenticated/…、publishable keyのみ 200 400

非公開バケットは、存在しないかのように応答します。これが望ましい動作です。公開バケットは、パスを推測できる人、あるいは見つけた人に、ファイルを渡してしまいます。

URLがそれほど重要なのはなぜ?

公開ファイルの秘密度は、そのパスと同じ程度です。パスは予測しやすいことが多く、ユーザーID、日付、請求書番号などが使われがちです。ページのソース、共有されたリンク、ブラウザの履歴、ログからも漏れます。公開バケットに置いた請求書、パスポートのスキャン、署名済みの契約書は、事実上、公開されたのと同じです。

どう選んで、どう直す?

  • 公開バケット: アバター、商品写真、ブログの画像など、全員に向けたファイル。バケットにファイルサイズの上限と許可するMIMEタイプを設定して、ポリシーが許す公開アップロード経路で別のものをホストされないようにします。
  • 非公開バケット: ドキュメント、エクスポート、請求書など、個人に関わるすべて。ユーザーのセッションでダウンロードするか、期限付きの署名付きURLを作成します。

バケットと、その制限を確認するには次のクエリを使います。

select id, public, file_size_limit, allowed_mime_types
from storage.buckets
order by public desc, id;

非公開バケットには、storage.objectsのポリシーも必要です。通常は、パスの最初のフォルダがユーザーIDか会社IDであることを確認します。プロジェクトを移行したあとは、そのポリシーの数を数えてください。あるアプリでは、ポリシーのマイグレーションが実行されなかったためにすべてのアップロードが失敗しました。それはLovableアプリのセキュリティチェックリストに書いています。publishable keyがほかに何へ到達できるかは、Supabaseのanon keyとservice role keyの違いにあります。

© 2026 Denys Zaichenko. 元の記事: https://madsalt.tech/ja/notes/supabase-public-bucket/