Skip to content
ShipSecurelySecurity reference
Menu
Your tool here — sponsor ShipSecurely

Issues

Open storage buckets

A public bucket, or a storage policy of allow-all, lets anyone with the URL read files other users uploaded.

Share link · Share on X

Last updated

criticalDatabase

Shows up in: Supabase, Firebase, Vercel

Markdown version

What it is

Table RLS does not apply to files. Supabase Storage and Firebase Storage have their own policies. A bucket flagged public, or a policy of allow read: if true, means the object URL is the only secret. URLs leak through the network panel, emails, and referrers.

"Public" is appropriate for assets you meant to publish, such as marketing images. It is not appropriate for invoices, IDs, or user uploads you thought were private because the UI does not link to them.

Listing and reading are different. A bucket can hide the file list and still serve any object whose name is known. Generated names help. A private policy helps more.

How to check in 5 minutes

  1. In Supabase, open Storage and look at each bucket's public flag and policies. In Firebase, open Storage rules.

  2. Copy a file URL from one test user. Open it in a private window with no login. If the file loads and it was not meant to be public, the bucket is open.

  3. As a second test user, request the first user's object path through the client SDK. If the SDK returns it, the policy is too wide even when the bucket is marked private.

  4. Search the repo for getPublicUrl and public: true. Those call sites are public by intent. Confirm each one should be.

How to fix

Supabase

Make the bucket private. Add policies so authenticated users can only read and write a prefix that includes their user id.

create policy "own folder read"
on storage.objects
for select
to authenticated
using (
  bucket_id = 'uploads'
  and (storage.foldername(name))[1] = auth.uid()::text
);

Write the matching insert and update policies with with check. Serve files to the owner with a short-lived signed URL created on the server after you check the session. Do not generate signed URLs for any path the caller passes. Check the prefix first.

Firebase

rules_version = '2';
service firebase.storage {
  match /b/{bucket}/o {
    match /uploads/{userId}/{file} {
      allow read, write: if request.auth != null && request.auth.uid == userId;
    }
  }
}

That sample is the shape, not a complete ruleset. Add size and content-type checks from unsafe file uploads. Do not deploy if true because a test upload failed.

Vercel

If files live on Vercel Blob or another store, start from private access and issue signed reads. Check that product's docs for the exact flag. A file in public/ on the Next.js app is always public. Do not put user uploads there.

Next.js

The route that mints a signed URL has to authenticate the caller and authorize the path. A route that signs whatever ?path= it receives is an IDOR. See IDOR.

Copy-paste prompt

Paste this into Cursor, Claude Code, or whichever agent is editing the repo. Read the diff before you merge it.

You are closing open file storage. Do not add features.

1. Find buckets, Blob stores, and public/ folders used for uploads.
2. Make user-file buckets private. Leave truly public marketing assets public and list them in your summary.
3. Add read and write rules so a user can only access their own path prefix.
4. Replace unlimited public URLs with short-lived signed URLs created only after a session check.
5. Do not sign a path just because the client sent it.

Show the policy and the signing code. Tell me how to confirm a logged-out request no longer loads another user's file.

Questions

The bucket is private but getPublicUrl still works. How?

getPublicUrl builds a URL. It does not check the policy. If the bucket is actually private, that URL should fail when you open it logged out. If it loads, the object or the bucket is still public.

Are signed URLs safe to put in an email?

They are a bearer token for that file until they expire. Use a short expiry. Do not use a year-long URL as a convenience.

Sources

Related