Home / Supabase Security Audit
Security guide · 2026

Supabase Security Audit

RLS policies, secret key exposure, Edge Function auth, and Storage bucket permissions — the four layers that fail most often.

OWASP Top 10 CWE Top 25 CVSS v3 CVE-2025-48757
TL;DR: Supabase is secure by design. The vulnerabilities in Supabase-based apps come from configuration defaults — RLS is off by default, service_role keys end up in client bundles, and Edge Functions often skip JWT verification. CVE-2025-48757 (May 2025) documented 170+ production apps with fully readable databases — no login required. Average score on first scan: 42/100. All gaps are fixable once identified. Free scan: launchreadycode.com.

The 4 Supabase security layers to audit

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.

Layer 1 — Critical
Row-Level Security (RLS)

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.

Layer 2 — Critical
Secret Key Exposure

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.

Layer 3 — High
Edge Function Auth

Edge Functions that do not verify the caller's JWT allow unauthenticated execution of server-side logic, API calls, and database mutations.

Layer 4 — Medium
Storage Bucket Permissions

Storage buckets created as "public" expose all files without authentication. Private buckets with permissive policies grant access beyond intent.

The 3 diagnostic SQL queries

Run these in your Supabase SQL editor to diagnose RLS issues in under 5 minutes.

Query 1 — Tables with RLS disabled (publicly accessible)

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

Query 2 — Tables with RLS on but no policies (fully locked)

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

Query 3 — Permissive USING(true) policies (everyone gets full access)

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)
Run Query 1 now. Any table showing 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.

What an LRC Supabase audit finds, in numbers

Based on scans run through launchreadycode.com as of June 2026:

42/100 — average score across Supabase apps (first scan)

How to fix Supabase RLS

-- 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';

Scan my Supabase app — free

URL-based scan. No code access. No signup. Free Launch Readiness Score in 60 seconds — security, reliability, performance, monitoring.

Scan my Supabase app — free

Frequently asked questions

Is Supabase secure?

Supabase 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.

What is the service_role key risk?

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.

How do I check Supabase RLS?

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.

What is CVE-2025-48757?

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.

How much does a Supabase security audit cost?

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