Home  /  Blog  /  Supabase Security Checklist: 12 Checks Before You Go Live

● Database Security

Supabase Security Checklist: 12 Checks Before You Go Live

Supabase lets you ship in a weekend, and most Supabase data leaks are not clever hacks, they are a missed checkbox. New tables have row-level security off by default, the service_role key bypasses everything, and views and functions quietly ignore RLS. This is the practical pre-production checklist we run before any Supabase app handles real user data.

Published 7 November 2026 12 min read Codesecure Application Security Database Security

Key Takeaways

  • Most Supabase data leaks come from a missed check, not a sophisticated attack. New tables ship with RLS off by default.
  • The anon key is meant to be public and is safe to expose only when RLS is correct. The service_role key bypasses RLS and must never reach the browser.
  • Views and SECURITY DEFINER functions can ignore RLS. Review every client-facing view and function, and prefer SECURITY INVOKER.
  • Enabling RLS with no policy denies all access, which is the safe starting point. Then add explicit, scoped policies with a WITH CHECK clause.
  • Test both allowed and denied paths with two separate users before launch, and re-run the checklist after every schema change.

Why a Checklist Beats a Clever Defence

Supabase is a joy to build on because it removes boilerplate, but that same speed hides security decisions behind sensible-looking defaults. The result, seen again and again in 2026, is that the typical Supabase incident is not an exotic exploit, it is a table that shipped with row-level security disabled, or a service_role key that ended up in a frontend bundle. Those are checkbox failures, and a checkbox is exactly how you prevent them.

Supabase publishes its own production checklist, and you should run it. The list below complements it with the database-layer checks an attacker actually probes: not just whether RLS is on, but whether your policies, views, functions and grants hold up when someone calls the API directly instead of using your app.

Checks 1 to 3: Row-Level Security Fundamentals

Row-level security is the foundation, and it has to be deliberate on every table. Remember that CREATE TABLE leaves RLS off, so any table you added quickly, or a collaborator added, may be wide open to the anon key. Enabling RLS with no policies is the safe default: it denies everything until you add explicit grants.

  • RLS enabled on every exposed table. Check the Supabase dashboard or pg_class.relrowsecurity. A single table without RLS in a client-exposed schema is readable and writable by anyone with the anon key.
  • Every table has explicit, scoped policies. Scope reads and writes to the authenticated user's own data, for example (select auth.uid()) = user_id, never a blanket true.
  • Every UPDATE, INSERT and ALL policy has a WITH CHECK clause. Without it, the new row is not validated and no column is protected, so a user can rewrite columns you never intended.

Worried Your Supabase RLS Has These Gaps?

Codesecure audits Supabase and PostgreSQL row-level security the way an attacker tests it: every policy, every SECURITY DEFINER function, every anon and authenticated grant. We deliver a prioritised findings report with exact remediation SQL. ISO/IEC 27001:2022 certified delivery, named OSCP and CEH consultants, fixed-price proposals, for businesses across India, Singapore, UAE and Malaysia.

See Database Security Services →

Checks 4 to 5: The Two Keys That Decide Everything

Supabase gives you two keys, and confusing them is behind many leaks. The anon key is designed to live in your frontend and is safe to expose precisely because RLS stands between it and your data. The service_role key is the opposite: it bypasses RLS entirely and is effectively a master key, so it belongs only on a trusted server.

  • The service_role key is server-side only. Grep your client bundle, environment variables and git history for it. If it has ever shipped to a browser or a public repo, rotate it now.
  • The anon key is protected by RLS, not by secrecy. Treat it as public, and make sure RLS is correct so that being public is safe. If removing RLS would expose data to the anon key, that data is one mistake away from exposure.

Checks 6 to 7: Views and Functions That Ignore RLS

Two database objects quietly sidestep row-level security, and both are easy to miss because the table underneath looks locked down.

  • Review every client-facing view. Views can run with the view owner's rights and bypass the RLS on their underlying tables. Recreate client-facing views with security_invoker = true so the caller's policies apply.
  • Audit every SECURITY DEFINER function. They run as the owner and ignore RLS, and Supabase exposes them at /rest/v1/rpc/ with EXECUTE granted to PUBLIC by default. Revoke EXECUTE from anon and public, authorise auth.uid() inside the body, and prefer SECURITY INVOKER for read-only functions.

Checks 8 to 10: Grants, Storage and Secrets

RLS is one layer. The grants, storage policies and secret handling around it decide your blast radius when something else slips.

  • Least-privilege table grants. By default roles can be granted broad privileges. Revoke TRUNCATE, REFERENCES and TRIGGER, and any DML, that anon and authenticated do not need, so a single dropped policy does not expose full CRUD.
  • Storage bucket policies. Object storage needs the same owner checks as tables. Confirm private buckets are not readable or writable by anon, and that signed URLs are scoped and time-limited.
  • No secrets in readable columns. SMTP passwords, API keys and tokens belong in Supabase Vault or an encrypted, write-only field, never in a column that is returned to the client or captured in backups.

Not Sure If Your Policies Are Safe?

Send us your Supabase project and we will scope a row-level security review on a free 30-minute call. We assess RLS coverage, column exposure, RPC bypass paths and tenant isolation, then hand you the fixes.

Book a Free Scoping Call →

Check 11: Test Allowed and Denied Paths With Two Users

Policies are code, and untested code is a guess. The single most valuable pre-launch step is to actually exercise your access rules. Create two test accounts in different tenants and, for every sensitive table and RPC, confirm that the allowed path works and, more importantly, that the denied path fails: user A must not read, update or delete user B's rows, and the anon role must not reach anything it should not.

Run these tests against the REST API and the RPC endpoints directly, not through your UI, because an attacker will. This is also where a professional review adds the most value: we script these cross-tenant and anonymous tests across your whole schema so no table is assumed safe just because the dashboard says RLS is on.

Check 12: Harden the Account, Then Re-Check

Finally, protect the project itself and keep the checklist alive. Enable multi-factor authentication on your Supabase account, review who has access to the project, and use the built-in Security Advisor to catch obvious database issues. Then treat this list as a recurring gate: because RLS is off by default on new tables and new functions default to broad EXECUTE, every schema change can reopen a gap you already closed.

Bake the checks into your deployment process so a new table or function cannot reach production without passing them. Security that is a one-time launch task decays with the next migration; security that is a repeatable check holds.

SHARE

Frequently Asked Questions

Is Supabase secure by default?

Supabase gives you strong security tools, but the defaults are not fully locked down. New tables have row-level security disabled until you enable it, functions default to broad EXECUTE, and views can bypass RLS. Supabase is secure when you configure RLS on every exposed table, write scoped policies, keep the service_role key server-side, and audit views and functions. The platform provides the controls; you have to turn them on.

Is it safe to expose the Supabase anon key in frontend code?

Yes, the anon key is designed to live in your frontend, but only if row-level security is correctly configured on every table it can reach. RLS is what stands between the public anon key and your data. If a table has RLS disabled or an overly permissive policy, the anon key becomes a master key to that table. So the anon key is safe to expose precisely to the extent that your RLS is correct.

What is the difference between the Supabase anon key and the service_role key?

The anon key is a public key for your frontend and is fully subject to row-level security. The service_role key bypasses RLS entirely and acts as a superuser over your data, so it must only ever be used on a trusted server and must never appear in client code, environment variables shipped to the browser, or a public repository. If the service_role key leaks, rotate it immediately.

Do I need RLS on every table in Supabase?

On every table exposed through the API, yes. Any table in a client-accessible schema without row-level security is readable and writable by anyone holding the anon key. Enable RLS on every such table, and remember that new tables ship with RLS off, so this is a check to repeat after each migration, not a one-time task.

How do I test my Supabase RLS before launch?

Create two test users in different tenants and, for each sensitive table and RPC, verify the allowed path works and the denied path fails: user A must not access user B's rows, and the anon role must not reach protected data. Run the tests directly against the REST and RPC endpoints, not through your UI, because that is how an attacker reaches them.

Can Codesecure review our Supabase project before we go to production?

Yes. Codesecure runs a pre-production Supabase security review covering RLS coverage, policy scoping and WITH CHECK, anon and service_role key handling, views, SECURITY DEFINER functions, grants, storage and secrets, and we script cross-tenant and anonymous tests across your schema. You get a prioritised report with the exact fixes. ISO/IEC 27001:2022 certified delivery with named OSCP, CEH and CISSP consultants.

CS

Codesecure Application Security

OSCP / CEH / CISSP Certified Security Consultants

Codesecure Solutions is ISO/IEC 27001:2022 certified and runs manual application and database security assessments, including Supabase and PostgreSQL row-level security audits, API penetration testing and cloud security reviews, for businesses across India, Singapore, UAE and Malaysia. Named OSCP, CEH and CISSP consultants, fixed-price proposals, reports mapped to OWASP and ISO 27001.

✓ ISO/IEC 27001:2022 Certified

Ship Your Supabase App Without the Leak

Codesecure runs a pre-production Supabase review that tests RLS, keys, views, functions, grants and storage the way an attacker would, and hands you the exact fixes before you go live. ISO/IEC 27001:2022 certified delivery by named OSCP, CEH and CISSP consultants across India, Singapore, UAE and Malaysia.