RLS policies, secret key exposure, Edge Function auth, and Storage bucket permissions — the four layers that fail most often.
A Supabase security audit focuses on the four configuration layers that account for the large majority of critical and high-severity findings. These are not platform vulnerabilities — they are deployment decisions that AI builders routinely leave in their default (insecure) state.
Disabled by default on every table. Any authenticated or anonymous user with the anon key can read and write all data. The CVE-2025-48757 class.
The service_role key bypasses all RLS. If it appears in a client bundle or Git history, your entire database is exposed regardless of RLS configuration.
Edge Functions that do not verify the caller's JWT allow unauthenticated execution of server-side logic, API calls, and database mutations.
Storage buckets created as "public" expose all files without authentication. Private buckets with permissive policies grant access beyond intent.
Run these in your Supabase SQL editor to diagnose RLS issues in under 5 minutes.
SELECT schemaname, tablename, rowsecurity FROM pg_tables WHERE schemaname = 'public' ORDER BY rowsecurity, tablename; -- rowsecurity = false means the table is publicly readable and writable -- rowsecurity = true means RLS is on — check policies next
SELECT t.tablename FROM pg_tables t LEFT JOIN pg_policies p ON p.tablename = t.tablename AND p.schemaname = t.schemaname WHERE t.schemaname = 'public' AND t.rowsecurity = true AND p.policyname IS NULL; -- These tables have RLS enabled but zero policies -- Result: inaccessible to everyone including authenticated users -- Fix: add appropriate SELECT / INSERT / UPDATE / DELETE policies
SELECT tablename, policyname, cmd, qual FROM pg_policies WHERE schemaname = 'public' AND qual = 'true'; -- qual = 'true' means the policy allows ALL users to access ALL rows -- This is functionally the same as having RLS disabled -- Fix: replace USING (true) with USING (auth.uid() = user_id)
rowsecurity = false is readable by anyone who knows your Supabase project URL — which is in your client bundle. This is the exact attack vector documented in CVE-2025-48757.Based on scans run through launchreadycode.com as of June 2026:
-- Step 1: Enable RLS on every table ALTER TABLE users ENABLE ROW LEVEL SECURITY; ALTER TABLE posts ENABLE ROW LEVEL SECURITY; ALTER TABLE orders ENABLE ROW LEVEL SECURITY; -- Step 2: Create owner-scoped SELECT policy CREATE POLICY "users_select_own" ON users FOR SELECT USING (auth.uid() = id); -- Step 3: Create owner-scoped UPDATE policy CREATE POLICY "users_update_own" ON users FOR UPDATE USING (auth.uid() = id) WITH CHECK (auth.uid() = id); -- Step 4: Verify no permissive policies remain SELECT tablename, policyname, qual FROM pg_policies WHERE schemaname = 'public' AND qual = 'true';
URL-based scan. No code access. No signup. Free Launch Readiness Score in 60 seconds — security, reliability, performance, monitoring.
Scan my Supabase app — freeSupabase is a well-engineered platform with strong security primitives. The vulnerabilities found in Supabase-based apps come from configuration defaults — RLS is disabled by default on every table, a design choice documented in Supabase's own docs. AI builders scaffold schemas without enabling RLS, creating apps where the database is publicly accessible. All of these gaps are standard infrastructure hardening steps, fixable once identified.
The service_role key bypasses all RLS policies by design — it is meant for server-side administrative operations only. If it ends up in a client-side JavaScript bundle (common in AI-generated code that uses a single Supabase initialisation file for both client and server), any visitor to your app can extract it from their browser's DevTools and use it to read, modify, or delete your entire database. Rotate the key immediately and store it exclusively in server-side environment variables.
Run this SQL in your Supabase SQL editor: SELECT schemaname, tablename, rowsecurity FROM pg_tables WHERE schemaname = 'public' ORDER BY rowsecurity, tablename; Any row with rowsecurity = false is publicly accessible. Then check for permissive policies: SELECT tablename, policyname, qual FROM pg_policies WHERE schemaname = 'public' AND qual = 'true'; Policies with qual = 'true' allow all users access to all rows. For a complete automated check, use the free scanner at launchreadycode.com.
CVE-2025-48757 is a class of misconfiguration documented in May 2025 affecting 170+ production apps built with AI tools using Supabase. The root cause: RLS is disabled by default in Supabase; AI builders scaffold schemas without enabling it; the public anon key (embedded in the client bundle by design) could then be used to query any table and return all rows with no authentication required. The fix is enabling RLS on every table and replacing any USING (true) policies with owner-scoped USING (auth.uid() = user_id) policies.
A free Launch Readiness Score is available at launchreadycode.com — URL-based, no signup, 60 seconds. The full Launch Readiness Audit Report covering all findings with severity, file references, and specific fixes is $499 one-time, delivered in under 2 minutes. Ongoing daily monitoring starts at $149/month. The Code Care DFY Technical Setup ($1,999 setup fee + $2,999/mo) implements every fix — RLS policies, secret management, Edge Function auth, monitoring setup — with a senior engineer reviewing and applying every change.
Sources: CVE-2025-48757 (NVD / Matt Palmer, May 2025); byteiota.com/supabase-security-flaw-170-apps-exposed-by-missing-rls; OWASP Top 10 2021; CWE Top 25 2024; Supabase documentation. This page provides general security guidance, not a certification or guarantee.
Compliance Wing
Security fixed. Now check your compliance.
EU AI Act enforcement is now live — fines up to €35M for undisclosed AI systems. GDPR, SOC 2 foundations, and ISO 27001 foundations are separate obligations your security scan does not cover. One additional scan, 52 checks, 3 minutes. $799 — credited toward full implementation if you need it.
Run Compliance Score — $799 → 7-day money-back · No code access required