Reconvio
Back to blog
Security 3 min read

Supabase RLS: the one setting that decides who reads your data

Row Level Security is the difference between a private database and a public one — and it's the setting AI builders quietly skip. What RLS is, how to tell if yours is off, and how to switch it on without breaking your app.

Marek Křivan · July 18, 2026
Supabase RLS: the one setting that decides who reads your data

Supabase is genuinely excellent, and its design has one detail that trips up almost every AI-built site: the anonymous key is meant to be public. It ships in your frontend on purpose. The only thing standing between "public key" and "public database" is a feature called Row Level Security — and if it's off, that public key is a skeleton key to your data.

This is the quiet finding. The site works perfectly. Nothing looks broken. And meanwhile anyone can read your users table straight through the API.

What RLS actually is

Row Level Security is a set of rules, per table, that decide which rows a given request is allowed to see or change. With RLS on and a policy written, an anonymous visitor might read your public product catalogue but not the users table. With RLS off, the anon key can read — and sometimes write — everything.

That's the whole game. RLS is the permission layer. Without it, there is no permission layer.

Why AI builders skip it

Because the app works without it. When you're building, you are the only user, and wide-open access means everything Just Works on the first try. RLS is invisible until the moment a stranger reads data they shouldn't — and by then it's a breach, not a bug report. AI optimises for the first-try success, so it leaves RLS off and moves on. Independent reviews of AI-built apps in 2026 found the overwhelming majority were missing RLS on at least one table holding real user data.

How to tell if yours is off

Two ways:

  • By hand: grab your project's anon key (it's in your frontend bundle) and query a sensitive table through the REST API. If rows come back without a login, RLS is off or too loose.
  • The fast way: Reconvio runs a safe, count-only check — it confirms whether a table is readable and counts the rows, but never reads or stores the data itself. You find out you're exposed without anyone actually exfiltrating anything.

How to switch it on without breaking your app

This is where people panic and either do nothing or blanket-lock everything (which breaks the site). Neither is right. Do it deliberately:

  1. Decide what's genuinely public. A product catalogue or published articles are meant to be read anonymously — leave those readable so the site keeps working.
  2. Enable RLS on everything else and write a policy per table. Anonymous access must not be able to read users and their personal data, roles and permissions (who's an admin), orders, or payments.
  3. Never allow anonymous writes. Insert / update / delete for the anon role should be off, full stop.
  4. Keep the service_role key server-side. It bypasses RLS entirely by design, so it must never appear in your frontend. If it's in the bundle, rotate it now and move those calls to a server function.

The mistake to avoid in both directions: don't blindly turn RLS on for every table (you'll break your working public reads), and don't write one permissive "allow all" policy just to make the error go away (that's the same hole with extra steps).

Where this fits

Missing RLS is item #2 on my complete security checklist for AI-built sites, and one of the five holes I find on almost every AI-built site. It rarely travels alone — a site careless enough to leave RLS off usually has a leaked key in its frontend too.


The anon key being public is not the bug. The bug is assuming "public key" means "public data is fine". RLS is the setting that makes that assumption safe — or, when it's off, catastrophic. Takes thirty seconds to find out which. Check your site.

See what your site exposes

Run a free audit and get concrete issues in half a minute — no signup.

Check my website