What Is This Vulnerability
A listable storage bucket allows users to enumerate all files within the bucket, discovering file names, paths, sizes, and metadata. Even if individual files require authentication to download, the ability to list bucket contents reveals sensitive information about what is stored. In Supabase, bucket listing is controlled by RLS policies on the storage.objects table.
When no SELECT policy is configured on storage.objects (or when the policy is overly permissive), any user can call the list endpoint and see all files across all users.
// An attacker can enumerate all files in a bucket
const { data } = await supabase.storage
.from('user-uploads')
.list('', { limit: 1000 });
// Returns all file names, sizes, and metadata
Why It's Dangerous
Bucket enumeration enables several attack vectors:
- Information disclosure: File names often reveal their contents (e.g.,
tax-return-2025.pdf,passport-scan.jpg) - User enumeration: If files are organized by user ID, an attacker can discover all user IDs in the system
- Targeted downloads: Even if the bucket is private, knowing exact file paths allows an attacker to attempt signed URL exploits or wait for misconfiguration
- Metadata exposure: File sizes, creation dates, and MIME types reveal usage patterns and data types
- Social engineering: Knowledge of what files exist helps attackers craft convincing phishing or pretexting attacks
In combination with a public bucket, listing access means an attacker can systematically download every file in your storage.
How to Detect
Attempt to list files in each bucket as both anonymous and authenticated users:
// Test as anonymous user
const { data, error } = await supabase.storage
.from('bucket-name')
.list('', { limit: 10 });
if (data && data.length > 0) {
console.log('Bucket is listable!', data);
}
Check RLS policies on the storage objects table:
SELECT policyname, cmd, qual, roles
FROM pg_policies
WHERE schemaname = 'storage'
AND tablename = 'objects'
AND cmd = 'SELECT';
AuditYourApp tests listing capability on every bucket it discovers and reports whether file enumeration is possible for anonymous users, authenticated users, or both.
How to Fix
Add restrictive SELECT policies on storage.objects that limit listing to owned files:
-- Users can only list files in their own folder
CREATE POLICY "Users can list own files"
ON storage.objects FOR SELECT
TO authenticated
USING (
bucket_id = 'user-uploads'
AND (storage.foldername(name))[1] = auth.uid()::text
);
Structure your bucket with user-specific prefixes to enable this pattern:
user-uploads/
{user-id-1}/
document.pdf
photo.jpg
{user-id-2}/
report.xlsx
If you need admin users to list all files, add a separate policy:
CREATE POLICY "Admins can list all files"
ON storage.objects FOR SELECT
TO authenticated
USING (
EXISTS (
SELECT 1 FROM user_roles
WHERE user_id = auth.uid() AND role = 'admin'
)
);
Never allow the anonymous role to list bucket contents unless the bucket genuinely contains only public assets.
Scan your app for this vulnerability
AuditYourApp automatically detects security misconfigurations in Supabase and Firebase projects. Get actionable remediation in minutes.
Run Free Scan