Supabase Storage bucket RLS — buckets need policies too
Storage buckets default-allow read in tutorials. Add RLS policies + signed URLs for downloads.
Supabase Storage has its own RLS layer. Tutorials often skip; default-public buckets leak everything.
What it is
Storage = the Supabase file-storage service. Buckets need RLS policies on storage.objects, not just on regular tables.
Vulnerable example
-- Public bucket — every file readable
create policy "anyone_reads" on storage.objects for select using (true);Fixed example
-- Per-user-scoped bucket
create policy "users_read_own_files" on storage.objects for select
using (
bucket_id = 'user-uploads'
and auth.uid()::text = (storage.foldername(name))[1]
);
create policy "users_insert_own_files" on storage.objects for insert
with check (
bucket_id = 'user-uploads'
and auth.uid()::text = (storage.foldername(name))[1]
);
-- Use signed URLs for downloads (never public-bucket)How Securie catches it
supabase/migrations/0042_orders_rls.sql:14Supabase Storage bucket RLS
Supabase RLS specialist scans storage policies + flags default-public + missing-per-user-scope.
-- Per-user-scoped bucket
create policy "users_read_own_files" on storage.objects for select
using (
bucket_id = 'user-uploads'
and auth.uid()::text = (storage.foldername(name))[1]
);
create policy "users_insert_own_files" on storage.objects for insert
with check (
bucket_id = 'user-uploads'
and auth.uid()::text = (storage.foldername(name))[1]
);
-- Use signed URLs for downloads (never public-bucket)Checklist
- RLS enabled on storage.objects
- Per-user folder scoping
- Signed URLs for downloads (1h TTL max)
- Strict content-type on upload
FAQ
Public bucket for landing-page assets?
OK if intentional. Mark bucket public explicitly + understand the trade-off.
Related guides
Row-Level-Security bypass is the most common data leak in vibe-coded apps. Here is exactly how it happens, how attackers find it, and how to fix it in Next.js + Supabase with one policy update.
The service-role key bypasses every RLS policy you wrote. It exists for a reason; it leaks for many reasons. Here is the rule for when to use it, the patterns that leak it, and the recovery playbook when it does.
anon key is public BY DESIGN — without RLS it's a skeleton key. Lovable Apr 2026 BOLA showed 10.3% of apps got this wrong.
File uploads are the most commonly mis-handled feature in AI-built apps. Here is the five-step pattern for uploading user files safely.