All articles

Supabase security scan checklist before you launch

8 min read

Free security scan

Is your Next.js app secure? Find out in 30 seconds.

Paste your URL and get a full vulnerability report — exposed keys, missing headers, open databases. Free, non-invasive.

No code access requiredSafe to run on productionActionable report in 30

A supabase security scan is a focused prelaunch review of the places where Supabase apps most often leak data: Row Level Security, browser-exposed keys, storage buckets, auth redirects, and server-only secrets. The fastest useful answer is this: verify every public table has RLS enabled, test policies as real users, block privileged keys from the client, and scan the deployed app before users arrive.

Supabase security scan checks

Start with the controls that can expose customer data in minutes, not theoretical issues. Supabase is safe to use, but its flexibility makes mistakes easy when an AI builder, template, or rushed launch creates database tables faster than policies are reviewed.

Focus first on:

  • RLS coverage on every table reachable from the browser
  • Anon key behavior tested against real user roles
  • Service role isolation from client bundles and public logs
  • Storage bucket access for uploads, avatars, invoices, and exports
  • Auth redirect controls for magic links, OAuth, and password reset flows
  • Public secret exposure across frontend code, source maps, and environment files

A good Supabase security check should not stop at settings screenshots. It should prove what an unauthenticated visitor, a normal user, and a malicious logged-in user can actually read or write.

For example, a table can have RLS enabled but still expose rows because a policy uses true, trusts client-supplied fields, or forgets tenant boundaries. The practical test is simple: log in as User A and attempt to read, update, or delete User B's records through the same API path your frontend uses.

You should also scan the deployed site, not only the repository. Build tools can inline values, leave source maps public, or ship old bundles after a bad rollback. A security scan helps catch browser-visible exposures that are easy to miss in local review.

High-risk Supabase failure patterns

The most serious failures usually come from one of four patterns. They are common in fast AI-assisted builds because generated code often prioritizes a working demo over a safe data boundary.

The first is missing RLS entirely. A table created for profiles, orders, messages, or team membership may work during development because the anon key can read it. If RLS is off, your frontend can become a public database browser.

The second is overbroad policy logic. A policy like using (true) may be acceptable for public marketing content, but not for user data. Policies should usually bind rows to auth.uid(), organization membership, or a verified server-side claim.

The third is leaked privileged keys. Supabase anon keys are designed for client use when RLS is correct. Service role keys are different. They bypass RLS and must never appear in frontend JavaScript, mobile builds, public repos, error tracking payloads, or support screenshots.

The fourth is unsafe storage access. Teams often protect database rows but forget bucket policies. A private invoice PDF, profile image, or exported CSV can become public if bucket rules allow anonymous reads or predictable paths.

A realistic database security review should include these quick abuse tests:

  1. Create two test users in separate accounts or organizations.
  2. Capture the browser request for a normal read operation.
  3. Change the requested row ID to another user's object.
  4. Try update, delete, upload, and download actions.
  5. Repeat the test while logged out.
  6. Confirm failures return safe errors, not full records.

If your app uses multi-tenant teams, test membership edges carefully. Invite flows, role changes, and deleted memberships often create stale access. A user removed from a workspace should immediately lose database and storage access, not only lose buttons in the UI.

For broader launch context, pair this with an AI app security audit and a public env check. Supabase issues rarely live alone. They often appear beside leaked .env files, permissive CORS, exposed admin paths, or debug routes.

Fix RLS before launch

Row Level Security is the core control for browser-connected Supabase apps. The official Supabase RLS documentation is worth reading, but your launch checklist should convert the concept into repeatable tests.

A basic policy should be narrow, readable, and tied to the authenticated user. Here is a simple example for user-owned profile rows:

sql
alter table public.profiles enable row level security;

create policy 'Users can read own profile'
on public.profiles
for select
to authenticated
using (id = auth.uid());

create policy 'Users can update own profile'
on public.profiles
for update
to authenticated
using (id = auth.uid())
with check (id = auth.uid());

This is not a universal policy. It is a safe pattern for one common shape: a profile row whose primary key matches the user ID. Team-based apps need membership checks, usually through an organization membership table.

The key detail is with check enforcement. A using clause controls which existing rows are visible for an operation. A with check clause controls which new or changed rows are allowed. Without it, updates and inserts can create privilege problems.

For insert policies, avoid trusting fields the user can choose unless the policy validates them. If the client can submit user_id, role, workspace_id, or is_admin, assume an attacker can change those values.

Server-side routes can use the service role key for trusted operations, but keep a strict boundary. Store it only in server environment variables, never expose it through NEXT_PUBLIC_, Vite public variables, client actions, or generated API responses.

A strong RLS review also checks views, functions, and RPC calls. Security-definer functions can accidentally bypass row rules. If a function returns sensitive data, test it as anon and authenticated users, not only through your normal UI.

Use a deep scan when you need a broader review of the deployed application surface. Database rules are critical, but attackers also look for bundled secrets, open admin panels, debug endpoints, and forgotten preview routes.

Prelaunch checklist

Run this checklist after staging is deployed and again after production configuration is set. Local checks are useful, but final behavior depends on real domains, environment variables, storage rules, and auth redirect URLs.

  • Inventory public tables and confirm RLS is enabled where browser access exists.
  • Test as anon and confirm private data is not readable without login.
  • Test as User A against User B records for read, write, delete, and upload paths.
  • Review insert policies for client-controlled ownership, roles, and tenant IDs.
  • Check storage buckets for public reads, signed URL rules, and predictable paths.
  • Search built assets for service keys, database URLs, JWT secrets, and webhook secrets.
  • Lock auth redirects to production and trusted preview domains only.
  • Remove debug endpoints that return session data, tokens, or raw database responses.
  • Rotate exposed keys if any secret reached a public bundle, log, or repository.

Pay special attention to generated code that calls Supabase directly from frontend components. That pattern is normal for safe anon operations, but dangerous when the component handles admin actions, billing changes, or cross-tenant data.

Also review error messages. A failed query should not return full SQL errors, table names, policy names, or internal object paths to the browser. Attackers use those details to map your schema and refine requests.

If you recently used AI-generated code, review assumptions line by line. Generated helpers may create broad queries like select('*'), client-side role checks, or hidden admin flags. The UI may hide data correctly while the underlying API still returns it.

For secrets specifically, use a dedicated exposed API keys workflow. Treat every public bundle, source map, and deployment artifact as searchable. If a key appears once in the browser, assume it has been copied.

A practical prelaunch security review is not about making Supabase complicated. It is about proving that the browser can only do what your product rules allow. If you verify RLS, isolate privileged keys, harden storage, and test real abuse paths, you remove the failures most likely to hurt users.

Faq

Is the Supabase anon key safe to expose?

Yes, the anon key is intended for browser use when Row Level Security and storage policies are correctly configured. It is not a secret by itself. The risk appears when RLS is disabled, policies are too broad, or the app exposes a service role key instead.

What should i scan first in a Supabase app?

Start with tables reachable from the frontend, especially profiles, organizations, messages, orders, billing records, and user-generated content. Confirm RLS is enabled, then test access as logged-out users and separate logged-in users. After that, scan storage buckets and deployed JavaScript for leaked secrets.

Do i need to rotate keys after a leak?

Rotate any service role key, webhook secret, database password, or third-party API key that appeared in public code, logs, or a deployed bundle. For anon keys, rotation is less urgent than fixing policies, but it can still help invalidate copied configuration after a public exposure.

If you want a fast external check before launch, run AISHIPSAFE against your production URL and review the findings before inviting users.

Free security scan

Is your Next.js app secure? Find out in 30 seconds.

Paste your URL and get a full vulnerability report — exposed keys, missing headers, open databases. Free, non-invasive.

No code access requiredSafe to run on productionActionable report in 30