← Back to blogSupabase Security Checklist: 8 Things to Lock Down Before You Launch

Supabase Security Checklist: 8 Things to Lock Down Before You Launch

Joel Martin·6 July 2026·7 min read

Supabase makes it incredibly easy to go from idea to working app. That's the point. But the same defaults that make development fast can leave your production app wide open if you don't tighten them before launch.

I've looked at dozens of Supabase-powered apps and the same issues come up every time. Most of them take less than ten minutes to fix. Here are the eight things you should check before real users touch your app.

1. Enable Row Level Security on every table

This is the big one. By default, when you create a table in Supabase, Row Level Security (RLS) is disabled. That means anyone with your project URL and anon key (which is in your frontend code) can read, write, and delete every row in that table.

-- Enable RLS
ALTER TABLE your_table ENABLE ROW LEVEL SECURITY;

-- Then add policies
CREATE POLICY "Users can read own data" ON your_table
  FOR SELECT USING (auth.uid() = user_id);

CREATE POLICY "Users can insert own data" ON your_table
  FOR INSERT WITH CHECK (auth.uid() = user_id);

CREATE POLICY "Users can update own data" ON your_table
  FOR UPDATE USING (auth.uid() = user_id);

Check every table. If a table has RLS disabled, anyone can query it directly through the Supabase REST API. This isn't a theoretical risk; it's trivially exploitable by anyone who views your page source and finds your Supabase URL.

Go to the Supabase dashboard, open Table Editor, and look for the "RLS disabled" warning on each table. If you see it, fix it before anything else.

2. Understand what the anon key can do

Your Supabase anon key is designed to be public. It ships in your frontend JavaScript. That's fine, but only if RLS is properly configured.

The anon key authenticates requests to the Supabase REST API with the anon role. Any RLS policy that allows the anon role to read or write data will be accessible to anyone with that key.

If you have tables where the RLS policy is something like:

CREATE POLICY "Anyone can read" ON public_posts
  FOR SELECT USING (true);

That's intentional for public data. But if you accidentally have a policy like that on a table containing user emails, private messages, or payment details, you've exposed all of it.

Review every RLS policy and ask yourself: "Is this policy correct for the anon role, not just for authenticated users?"

3. Restrict your API settings

In the Supabase dashboard, go to Settings, then API. Check these settings:

Exposed schemas: by default, Supabase exposes the public schema through the REST API. If you've created functions or tables in the public schema that shouldn't be accessible via the API, either move them to a different schema or restrict access with RLS.

Service role key: this key bypasses RLS entirely. It should never appear in frontend code, environment variables accessible to the browser, or client-side API calls. Use it only in server-side code (API routes, edge functions, backend services). If your service role key is in your frontend, anyone can bypass every security control you've set.

4. Lock down storage buckets

Supabase Storage has its own RLS-like policies. By default, new buckets are private, but many developers set buckets to public during development and forget to change them.

Check each bucket's policies:

-- Only allow users to upload to their own folder
CREATE POLICY "Users can upload own files" ON storage.objects
  FOR INSERT WITH CHECK (
    bucket_id = 'avatars' AND
    auth.uid()::text = (storage.foldername(name))[1]
  );

-- Only allow users to read their own files
CREATE POLICY "Users can read own files" ON storage.objects
  FOR SELECT USING (
    bucket_id = 'avatars' AND
    auth.uid()::text = (storage.foldername(name))[1]
  );

Without proper storage policies, users can list and download every file in a bucket, including files uploaded by other users. Organise uploads into user-specific folders and write policies that enforce ownership.

5. Configure authentication settings

Go to Authentication, then Settings in your Supabase dashboard.

Email confirmations: enable them. Without email confirmation, anyone can create an account with any email address, including email addresses that belong to other people.

Password requirements: set a minimum length. Supabase defaults to 6 characters, which is far too short. Set it to at least 10, preferably 12.

Rate limiting: Supabase has built-in rate limiting on auth endpoints, but check that it's enabled and set to reasonable values. Without rate limiting, an attacker can brute-force passwords or enumerate valid email addresses.

Disable signup if you don't need it: if your app is invite-only, disable public signups in the auth settings. Leaving signups open when you only expect a closed group of users is unnecessary attack surface.

6. Be careful with database functions

Supabase lets you create PostgreSQL functions and call them from the client via rpc(). These functions run with the permissions of the calling user by default, but if you create a function with SECURITY DEFINER, it runs with the permissions of the function creator (usually the postgres superuser).

-- DANGEROUS if not carefully controlled
CREATE OR REPLACE FUNCTION admin_delete_user(target_user_id UUID)
RETURNS void
LANGUAGE plpgsql
SECURITY DEFINER
AS $$
BEGIN
  DELETE FROM auth.users WHERE id = target_user_id;
END;
$$;

A SECURITY DEFINER function that's callable by the anon role means anyone can execute it with superuser privileges. If you need SECURITY DEFINER, add explicit permission checks inside the function:

CREATE OR REPLACE FUNCTION admin_delete_user(target_user_id UUID)
RETURNS void
LANGUAGE plpgsql
SECURITY DEFINER
AS $$
BEGIN
  -- Check that the caller is an admin
  IF NOT EXISTS (
    SELECT 1 FROM user_roles
    WHERE user_id = auth.uid() AND role = 'admin'
  ) THEN
    RAISE EXCEPTION 'Unauthorised';
  END IF;

  DELETE FROM auth.users WHERE id = target_user_id;
END;
$$;

7. Set up database backups

Supabase Pro plans include automatic daily backups. If you're on the free tier, you don't get automatic backups. Set up your own using pg_dump on a schedule.

This isn't strictly a security issue, but data loss from an accidental deletion or a compromised account is a security incident. Having backups means you can recover.

# Simple backup script
pg_dump $DATABASE_URL > backup_$(date +%Y%m%d).sql

Run this daily from a cron job on a separate server. Store backups somewhere your Supabase project can't access (so a compromised project doesn't compromise your backups too).

8. Monitor your usage and logs

Check the Supabase dashboard logs regularly. Look for:

Unusual API request volumes, which might indicate someone is scraping your data or brute-forcing your auth endpoints.

Failed authentication attempts, which might indicate a credential stuffing attack.

Unexpected RPC calls, which might indicate someone discovered and is calling functions they shouldn't be.

Set up alerts if your request volume spikes unexpectedly. Supabase provides usage metrics in the dashboard, and you can integrate with external monitoring tools.

How to check all of this

Go through each point manually. It takes about 30 minutes. For the externally visible issues (exposed API endpoints, public storage buckets, missing auth requirements), you can also run a scan with Hexora at hexora.uk to catch misconfigurations from the outside.

The internal configuration (RLS policies, function permissions, auth settings) requires reviewing your Supabase dashboard directly. No external scanner can check those for you, so this checklist is your starting point.

Ship it, but ship it locked down

Supabase is a brilliant tool for moving fast. None of these issues are Supabase's fault; they're the inevitable trade-off of a platform that prioritises developer speed. The defaults are designed for development, not production. Your job is to tighten them before real users and real data are involved.

Thirty minutes of configuration. Every user's data protected.

Worried about your own site's security? Get a free scan in seconds.

Scan your site for free