Check Supabase RLS before you launch an AI-built app
You built an app with an AI coding tool. The UI works. Auth seems fine. Before you put it on the internet, check whether every table that the browser can reach has Row Level Security (RLS) turned on, and whether the policies match what each role should be allowed to do.
This guide is a documentation review of Supabase's own docs, checked 2026-10-16. It does not report a runtime test of any app. No specific product is named as open or broken.
Supabase, Vercel, Next.js, Vite, GitHub and npm are named for identification only. ShipWithAI is not affiliated with or endorsed by them.
For a wider pre-launch checklist (backups, allowlists, logging), see Before you ship: lock the database, back it up, and log what happens. For keeping keys out of the frontend, see Keep secrets safe with AI coding tools.
Why this matters
Supabase's Row Level Security docs state that with no RLS, a table in an exposed schema can be read and written by any role that has a grant on it, and they say to enable RLS on every table in an exposed schema. (source, checked 2026-10-16)
The Production Checklist is blunt: tables without RLS and sensible policies "allow any client to access and modify their data". (source, checked 2026-10-16)
Our advice, not a vendor quote: AI tools often generate tables and leave policies for later. Treat that as a risk to check for, not as a statistic.
What "RLS on" actually does
RLS does not replace grants. It adds a second gate: even if a role has a grant on a table, each row still has to pass a policy for the operation. Supabase's RLS docs walk through enabling RLS, then adding policies, and note that with RLS on and no policies yet, the publishable key reaches no data. (source, checked 2026-10-16)
Our advice, not a vendor quote: do not enable RLS in one migration and "add policies later" on a live project without a plan. Prefer one migration that turns RLS on and adds the policies you need in the same change, as the docs' secure-a-table flow describes.
Know your keys
The publishable key is meant for the browser. The secret key must never ship to the client. Supabase's metaphor: the publishable key "only opens the lobby" and the secret key is "the master key". (source, checked 2026-10-16)
The same page notes that the legacy anon and service_role keys are being deprecated by the end of 2026. Prefer the publishable and secret names in new code, and know the legacy names when you search an older project.
On the RLS role table, service_role has full access and bypasses RLS. (source, checked 2026-10-16)
Search the frontend bundle and the repo for the secret key (and for service_role / sb_secret_). That search is the core of Vibe Coding Launch Kit prompt 06 (free sample).
Step-by-step check
- Run the Security Advisor in Studio, or
get_advisorswith type security via MCP, or the advisors path undersupabase dbon the CLI. Look for lint 0013 "rls disabled in public". (source, checked 2026-10-16) - In the Dashboard, confirm RLS is enabled on every table under Database > Tables. (source, checked 2026-10-16)
- For each table, follow the "Secure a table with RLS" procedure on the RLS page: grants, then policies, then
supabase test db. (source, checked 2026-10-16) - Enable RLS in a migration with
alter table <t> enable row level security;, and add the policies in the same migration. Once RLS is on and before policies exist, the publishable key reaches no data. (source, checked 2026-10-16) That loop matches Vibe prompt 07 (free sample). - Write policies only for what each role actually needs. Authenticated gets only the operations the app exposes. Do not use an "allow all" policy. (source, role/grant table, checked 2026-10-16)
- On server routes, also check ownership on the server. That point is grounded in OWASP A01 (Broken Access Control), not in Supabase's RLS page. It maps to Vibe prompt 08 in the paid kit.
Common mistakes
Secret key in a NEXT_PUBLIC_ or other client env var. The api-keys page above is the source for keeping the secret key off the client.
RLS on, but a write policy of using (true). Treat that as an example pattern to look for, not as a finding from a named project.
Policies that rely on user metadata. The advisors page lists lint 0015 "rls references user metadata". (source, checked 2026-10-16)
Free prompts for this checklist
The free Vibe Coding Launch Kit sample (3 prompts, no email) includes:
- 07 Check Supabase Row Level Security table by table — the core loop for this guide
- 06 Secrets sweep — key exposure
- 11 Pre-launch deploy checklist
The paid kit adds server-side access checks (08), a dependency check (09), a prompt-injection review (10) and rollback / first-hour steps (12).
Docs links checked 2026-10-16. Docs change, so re-check before relying on a procedure or lint code.
Related
- Before you ship: lock the database, back it up, and log what happens
- Keep secrets safe with AI coding tools
- Add user login safely to an AI-built app
- Prompt injection safety
Supabase, Vercel, Next.js, Vite, GitHub and npm are named for identification only. ShipWithAI is not affiliated with or endorsed by them.