/fix · supabase

Is my Supabase app secure?

Most apps built with AI tools keep their data in Supabase. Its public key is meant to be in the browser, which means row level security is what stands between that key and your tables.

What Supabase handles.

  • ✓A Postgres database with an API, sign-in, file storage and edge functions
  • ✓A publishable (anon) key designed to be exposed, limited by row level security
  • ✓Storage that refuses uploads to a bucket until a policy allows them
  • ✓A Security Advisor that flags tables in the public schema without row level security

From the platform’s own documentation: Supabase docs: API keys · Supabase docs: Row Level Security · Supabase docs: Storage access control · Supabase docs: Database Advisors

What stays yours.

  • →Row level security enabled on every table in an exposed schema, and a policy for each action
  • →Storage policies, and which buckets are public
  • →Secret and service_role keys kept on the server, set as edge function secrets
  • →Grants that policies do not take back
  • →Security headers on the app in front of it

Documented.

Public reports that involve Supabase or apps built on it, dated and linked. Each line says what its source says, and nothing more.

  1. May 29, 2025CVE-2025-48757: Supabase tables readable with the public key

    Matt Palmer found 303 endpoints across 170 Lovable-built projects where the public anon key in the browser allowed direct queries to Supabase tables that lacked row level security. He reported it privately on 2025-03-21 and published on 2025-05-29.

    Source: Superblocks, March 9, 2026
  2. June 2, 2026A scan of 1,072 Supabase-backed apps

    Symbiotic Security scanned 1,072 apps built with Lovable, v0, Bolt.new, Replit and Windsurf that use Supabase. It reports that 98% had at least one vulnerability, 308 exposed the anon key in JavaScript, 172 allowed data to be changed or deleted without signing in, and 197 had a CORS misconfiguration on the Supabase API.

    Source: Symbiotic Security, June 2, 2026

A five minute check.

In your own Supabase dashboard, in this order.

  1. Open the Security AdvisorIn the dashboard, open Advisors, then Security Advisor. A finding named rls_disabled_in_public means anyone with the project URL can read and change that table.
  2. Read every policyFor each table, read the policies for select, insert, update and delete. A condition of true opens the action to everyone the grant allows.
  3. Check the bucketsIn Storage, list which buckets are public. A public bucket is readable by anyone with the link, whatever its policies say.
  4. Find the secret keysSearch the frontend code and the published app for the secret or service_role key. It belongs only in server code and edge function secrets; if it ever shipped, rotate it.
  5. Check the grantsSupabase notes that adding policies does not revoke grants. If anon should never insert into a table, revoke the grant as well.

Questions.

Should I hide the anon key?

No. Supabase documents the publishable key as safe to expose in a web page or app. It is limited by row level security, which is where the attention belongs.

I enabled RLS and the app stopped loading data. Why?

That is RLS working. Once it is on, nothing is readable through the API until a policy allows it. Write the policy for each action the app needs, and no wider.

Is a public storage bucket ever right?

For files meant for everyone, such as product images, yes. ID documents, invoices and user uploads belong in a private bucket with policies.

Check the public side now.

Ten seconds. We read only what any visitor’s browser already sees, and store nothing.

Opens the app security check on this site with your address filled in.