Public Storage Buckets
Supabase storage buckets with overly permissive policies allow any user to upload, read, or delete files including other users' private documents and images.
How It Works
Supabase Storage uses policies similar to RLS to control file access. When buckets are marked as public or have permissive policies, any user can list, download, upload, or delete files. Attackers can enumerate file paths, access private user uploads (ID photos, documents, medical records), or upload malicious content. Even if the bucket is private, a policy like USING(true) on the storage.objects table makes every file accessible to anyone with the anon key.
-- Overly permissive storage policy
CREATE POLICY "allow_all_uploads" ON storage.objects
FOR ALL USING (bucket_id = 'user-files')
WITH CHECK (bucket_id = 'user-files');
-- Anyone can read/write/delete any file in user-files!-- Scoped storage policies
CREATE POLICY "users_upload_own" ON storage.objects
FOR INSERT WITH CHECK (
bucket_id = 'user-files' AND
(storage.foldername(name))[1] = auth.uid()::text
);
CREATE POLICY "users_read_own" ON storage.objects
FOR SELECT USING (
bucket_id = 'user-files' AND
(storage.foldername(name))[1] = auth.uid()::text
);Real-World Example
In 2023, a healthcare SaaS built on Supabase had public storage policies on their documents bucket. Patient medical records, lab results, and prescription images were accessible to anyone who guessed the file path structure, affecting thousands of patients.
How to Prevent It
- Organize files in user-specific folders: {user_id}/filename.ext
- Scope storage policies to auth.uid() matching the folder path
- Never mark buckets as public unless files are intentionally public
- Use signed URLs for temporary access to private files
Affected Technologies
Data Hogo detects this vulnerability automatically.
Scan Your Repo FreeRelated Vulnerabilities
Row Level Security Disabled
criticalSupabase tables without RLS enabled allow any authenticated or anonymous user to read, insert, update, and delete all rows using the client library.
RLS Policy with USING(true)
criticalRLS policies that use USING(true) or WITH CHECK(true) effectively disable row-level security by allowing all operations for all users.
RLS Enabled Without Policies
highRLS is enabled on a table but no policies are defined, which silently blocks all access including legitimate queries from your application.
Service Role Key Exposed
criticalThe Supabase service_role key is hardcoded in frontend code, committed to a repository, or exposed in client bundles, granting full database admin access to anyone.