Skip to content
BuildThenTestedSee packages

Supabase security: defaults, what breaks, what to check

Supabase is a hosted Postgres backend with auto-generated APIs, authentication, storage and edge functions. Below: what it configures by default according to its own documentation (verified 2026-09-21), the 15 patterns most associated with it, the security features the vendor offers and where they stop, and a checklist you can run without buying anything.

Key formats are changing (sb_publishable_ and sb_secret_); the docs state anon and service_role keys are deprecated by end of 2026.

Supabase is a hosted Postgres with an auto-generated API, auth, storage and edge functions. Its access model is the source of most public incidents in AI-built apps: the publishable (anon) key is meant to be public, and row-level security policies decide what that key can reach.

Supabase's docs state three things. Tables created in the dashboard get RLS enabled and tables created by SQL do not. The secret (service_role) key bypasses every policy. The Security Advisor flags tables without RLS. The checks below confirm those facts hold for your project.

Supabase defaults that matter for testing

Each row is taken from the vendor's documentation on the date shown. Defaults change; the date is the claim.

Defaults of Supabase as documented by the vendor
AreaDefaultSource
RLS on new tables (dashboard vs SQL)The Table Editor enables row level security when you create a table in the Dashboard; when you create a table with SQL you must enable it yourself.docs · verified 2026-09-21
Tables without RLSOn existing projects a new table in public starts with every privilege granted to all three roles. A table in an exposed schema without RLS is readable and writable by any role with a grant on it.docs · verified 2026-09-21
Anon / publishable key exposure modelPublishable keys (sb_publishable_, formerly anon) are safe to expose in web pages, apps and source code; anyone can read them, so they reach only what RLS allows, as the anon or authenticated role.docs · verified 2026-09-21
service_role / secret key scopeSecret keys (sb_secret_, formerly service_role) have BYPASSRLS and skip every RLS policy; the docs say never to put one in a browser, shipped app or source control. Legacy anon and service_role JWT keys are being deprecated by end of 2026.docs · verified 2026-09-21
Edge function authverify_jwt = true is the default and validates the JWT before the handler runs; with auth: 'none' every credential check is skipped and the handler must authorize itself.docs · verified 2026-09-21
Storage accessStorage does not allow uploads to buckets without RLS policies on storage.objects; public buckets are publicly readable; service keys bypass Storage RLS.docs · verified 2026-09-21

Documentation home: supabase.com/docs

What breaks in Supabase projects

45 patterns in the catalogue name Supabase; the most severe are listed here across secrets and keys, data access, login and permissions, payments, ai features. Attribution is descriptive: the default stack makes the pattern reachable, or a public incident names it.

Public incidents

A scan of 1,645 Lovable-built apps found 170 (about 10.3%) with database endpoints readable without login because Supabase row-level security policies were missing or too broad; recorded as CVE-2025-48757, CVSS 9.3.

  • 1,645 Apps scanned
  • 170 Apps with inadequate RLS
  • 10.3% Share of scanned apps
  • 303 Exposed endpoints
  • 9.3 Critical CVSS 3.1 base score (CVE record)
  • 8.26 Researcher's own CVSS base score
  • 2025-03-21 Scan date
  • 2025-05-29 Public disclosure

May 2025 · Matt Palmer (Replit, Inc.) · all sources

Moltbook, a social network for AI agents built with AI-generated code, ran a Supabase database without row-level security policies, leaving 1.5 million API tokens and 35,000 email addresses readable and writable without login.

  • 1.5 million API authentication tokens exposed
  • 35,000 Email addresses exposed
  • about 17,000 Human account owners in database
  • 2026-01-31 Reported to maintainer
  • 2026-01-31 (within about 2 hours) First fix applied

Feb 2026 · Wiz Research · all sources

One education app built on Lovable had 16 vulnerabilities, 6 critical; a database function denied callers whose role was 'authenticated', so anonymous callers passed and 18,697 user records were readable without login.

  • 16 Vulnerabilities found
  • 6 Critical
  • 18,697 User records exposed
  • 14,928 Unique email addresses
  • 870 Enterprise users with full PII

Feb 2026 · Taimur Khan · all sources

Lovable reported that from 3 February to 20 April 2026 a backend regression let any logged-in Lovable user read the chat history and source code of public projects; a fix shipped within two hours.

  • 2026-02-03 to 2026-04-20 Exposure window
  • 2026-02-22 First HackerOne report
  • about 2 hours Time from public report to fix

Apr 2026 · Lovable · all sources

Each entry links to its primary source in the evidence list. What to do about it is the self-check below.

Supabase's own security features, and where they stop

Stated from the vendor's documentation. The limits are the vendor's scope statements, not judgements.

  • Security Advisor and database lints

    Advisors run automatically in Studio and via CLI, MCP and the Management API, with ERROR-level lints such as rls_disabled_in_public, auth_users_exposed, sensitive_columns_exposed and WARN lints such as permissive_rls_policy (USING (true)).

    Where it stops: Checks schema configuration and policies; findings need manual confirmation against the intended schema, and runtime behaviour or application logic is outside their scope.

    vendor docs · verified 2026-09-21

  • Row Level Security

    Per-row Postgres policies that apply to publishable-key traffic; the RLS guide covers writing policies and testing them with pgTAP via supabase test db.

    Where it stops: Policies do not apply to secret-key traffic (service_role bypasses RLS) and must be enabled on SQL-created tables.

    vendor docs · verified 2026-09-21

  • Production checklist controls

    SSL enforcement, network restrictions, account MFA, email confirmations and rate limits (for example 2 emails per hour on the default SMTP) are documented dashboard settings.

    Where it stops: These are settings to turn on; the checklist lists them as steps rather than defaults.

    vendor docs · verified 2026-09-21

  • Auth and storage controls

    The product security page lists row and column level security, bot detection for auth, storage access control via RLS and custom roles.

    Where it stops: The page is an index of features; each needs configuration in the linked guides.

    vendor docs · verified 2026-09-21

Check it yourself, in this order

The critical patterns first. Each uses the dashboard and your browser.

NEXT_PUBLIC_ prefix on a secret

  1. In your hosting dashboard (Vercel: Project, Settings, Environment Variables) or your .env files, list every variable whose name starts with NEXT_PUBLIC_.
  2. For each one, ask whether the provider calls that value secret, private, server or admin. Stripe secret keys, model provider keys, database passwords and Supabase service_role keys all fall in that group.
  3. Open the live site in Chrome, right-click, choose Inspect, open the Sources tab and press Ctrl+Shift+F. Search for the first few characters of each suspect value.
  4. A bad result is a NEXT_PUBLIC_ variable holding a server-only key, or a search hit for that key's value in a loaded script.

Secrets committed to the code repository

  1. Open your project on GitHub (or the code view in your builder) and look at the file list for .env, .env.local, .env.production, serviceAccountKey.json or firebase-adminsdk files.
  2. Use the repository search box and search for sk_live, sk-, service_role, BEGIN PRIVATE KEY and password=.
  3. If you have the code on your computer, run one command in the project folder: git log --all -p -S sk_live -- . | head. Any output means a live key has been committed at some point.
  4. On GitHub, open Settings, then Code security, and check whether Secret scanning shows alerts.
  5. A bad result is any env or key file in the file list, any search hit that shows a real key, or an open secret scanning alert.

Service-role key shipped in the browser bundle

  1. Open your live app in Chrome, right-click anywhere and choose Inspect, then open the Sources tab.
  2. Press Ctrl+Shift+F (Cmd+Option+F on a Mac) to search every loaded file. Search for service_role and then for sb_secret_.
  3. Open the Network tab, reload the page, click any request whose address contains supabase.co, and read the apikey header under Request Headers.
  4. In the Supabase dashboard, open Project Settings, then API Keys, and compare that header value with your keys.
  5. A bad result is any search hit, or a header value that matches the service_role or secret key rather than the anon or publishable key.

Supabase pre-launch checklist

45 checks, in the order we run them. Usable without buying anything.

Self-check tool

Answer questions about your setup and get the patterns that apply, ordered by severity. Runs in your browser; nothing is sent.

Run the self-check

Packages for Supabase projects

Pre-launch check

Start here

For founders about to let real users in.

$490

Report in 48 hours
  • Keys and secrets in the browser or repo
  • Who can read and change whose data
  • Login, roles and admin routes
  • Errors, retries and rate limits
  • Debug mode, headers, deploy path

What you receive

Security sweep

For anyone who wants the three riskiest areas checked fast.

$290

Report in 24 hours
  • API keys and secrets in the bundle
  • Row-level rules on every table
  • Cross-user data reads
  • Admin and hidden routes
  • Client-only permission checks

What you receive

All packages and prices. Every report includes a re-check after your fixes.

Questions about Supabase

supabase rls audit

For every table your app touches: is RLS enabled, does each policy use auth.uid() or a role check rather than true, and can the publishable key read rows that belong to another user. We test each table with the anon key and two signed-in users and report which ones leak.

how do i know if my supabase rls is working

Open the SQL editor and run the query on the rls-disabled pattern page, or open Database Advisors and look for RLS Disabled in Public and Permissive RLS Policy. Then sign in as a second test user and try to load the first user's data in the app.

is the supabase anon key safe to expose

Yes, by design: Supabase's docs say publishable keys are safe in web pages and source code because RLS decides what they can do. The key that must never reach the browser is the secret (service_role) key, which bypasses every policy.