Supabase14 items

Supabase Security Checklist

Comprehensive security checklist for Supabase projects

Last updated 2026-01-15

Quick Checklist

  • 1Enable and enforce Row Level Security on all tables
  • 2Restrict anon key permissions to the minimum required
  • 3Use service_role key only on the server side
  • 4Enable email confirmation for new sign-ups
  • 5Configure custom SMTP for transactional emails
  • 6Set strong JWT expiry and refresh token rotation
  • 7Disable public schema access for unauthorized roles
  • 8Audit database functions for SECURITY DEFINER misuse
  • 9Enable SSL enforcement for all database connections
  • 10Configure network restrictions and IP allowlists
  • 11Review and restrict Realtime subscriptions
  • 12Set up proper CORS policies on Edge Functions
  • 13Enable Point-in-Time Recovery for production databases
  • 14Monitor auth logs and failed login attempts

Supabase Security Checklist

Supabase provides powerful primitives out of the box, but secure defaults still require deliberate configuration. This checklist covers the most critical areas to review before and after shipping a Supabase-backed application.

1. Row Level Security (RLS)

Every table exposed through the PostgREST API must have RLS enabled. Without it, any user with the anon key can read and write every row.

ALTER TABLE public.profiles ENABLE ROW LEVEL SECURITY;

CREATE POLICY "Users can read their own profile"
  ON public.profiles FOR SELECT
  USING (auth.uid() = id);

Run SELECT tablename FROM pg_tables WHERE schemaname = 'public' AND rowsecurity = false; to find unprotected tables. Even lookup tables that seem harmless should have explicit policies.

2. Anon Key vs. Service Role Key

The anon key is safe to embed in client code because RLS constrains what it can access. The service_role key bypasses RLS entirely and must never appear in frontend bundles, mobile app binaries, or version control. Store it in server-side environment variables only.

3. Auth Configuration

  • Enable email confirmation (Settings > Auth > Email Confirmations) to prevent account enumeration and spam sign-ups.
  • Configure a custom SMTP provider (Resend, Postmark, etc.) so emails are not rate-limited by the shared Supabase sender.
  • Set JWT expiry to a reasonable value (e.g., 3600 seconds) and enable refresh token rotation to limit the blast radius of token theft.
  • Disable any OAuth providers you are not actively using.

4. Database Hardening

-- Revoke default access on the public schema
REVOKE ALL ON SCHEMA public FROM anon, authenticated;
GRANT USAGE ON SCHEMA public TO anon, authenticated;
-- Grant only the specific tables and operations needed
GRANT SELECT ON public.posts TO authenticated;

Audit all functions marked SECURITY DEFINER. These run with the privileges of the function owner (often the superuser) and can inadvertently bypass RLS. Prefer SECURITY INVOKER when possible and always add explicit authorization checks inside the function body.

5. Network & Connection Security

  • Enable SSL enforcement in the Supabase dashboard so that database connections require TLS.
  • Use network restrictions to allowlist only the IP ranges that need direct database access (CI/CD servers, admin machines).
  • Avoid exposing port 5432 publicly; use the connection pooler when possible.

6. Realtime & Storage

Realtime subscriptions follow RLS policies, but misconfigured policies can leak data across channels. Test with multiple user sessions to confirm row-level filtering works as expected. For Storage, see the dedicated Storage Security Checklist.

7. Edge Function Security

All Edge Functions should validate the Authorization header and verify the JWT before performing any operations. Use CORS headers to restrict origins. Never trust client-supplied data without validation.

const authHeader = req.headers.get('Authorization');
const { data: { user }, error } = await supabase.auth.getUser(
  authHeader?.replace('Bearer ', '')
);
if (error || !user) {
  return new Response('Unauthorized', { status: 401 });
}

8. Monitoring & Incident Response

  • Enable the Logs Explorer and set up alerts for failed authentication attempts, RLS policy violations, and unusual query patterns.
  • Enable Point-in-Time Recovery (PITR) on production databases so you can restore to any point within the retention window after a breach or data corruption.
  • Regularly review the auth.audit_log_entries table for suspicious activity such as mass sign-ups or password resets from a single IP.

9. Secrets & Environment Variables

Store all secrets (Stripe keys, Resend API keys, third-party tokens) in Supabase Vault or Edge Function secrets. Never hard-code them in migrations or SQL functions.

By systematically working through each section you significantly reduce the attack surface of your Supabase project. Use AuditYour.app to automate detection of the most common misconfigurations.

Scan your app for this vulnerability

AuditYourApp automatically detects security misconfigurations in Supabase and Firebase projects. Get actionable remediation in minutes.

Run Free Scan