Row Level Security is the guardrail that most vibe-coded Supabase apps are missing, and it's the direct cause of the breaches you read about. The good news: it's just SQL, and an AI writes it well when you're specific. The bad news: a vague ask can produce SQL that either locks out your real users or, far worse, exposes all of them.
Here's "write the RLS policy for my users table" three ways to Claude via Claude Code, with the real SQL each produced. RLS is one of the few places a wrong policy is silently catastrophic, so the specificity really earns its keep.
The same request, three ways
"Write the RLS policy for my users table", three ways
Each prompt was given to Claude, via Claude Code (26 Sep 2026) on its own. SQL pasted verbatim.
add RLS to my users table
alter table users enable row level security;worseThis is the trap. RLS with no policy doesn't open access, it CLOSES it — enable this and forget the policies, and every query returns nothing. Your app looks broken.
write RLS on the users table so each user can read and update only their own row
alter table users enable row level security;
create policy "read own row"
on users for select
using (auth.uid() = id);
create policy "update own row"
on users for update
using (auth.uid() = id);it dependsNow users can read and update only their own row. auth.uid() is the logged-in user's id; the policy is a filter Postgres adds to every query on the table.
same policies, but deny insert and delete by default, and make sure a user can't update their row to impersonate another user; add a comment warning against using (true)
alter table users enable row level security;
-- No insert/delete policy = those are denied by default. That's intended.
create policy "read own row"
on users for select
using (auth.uid() = id);
create policy "update own profile"
on users for update
using (auth.uid() = id)
with check (auth.uid() = id);
-- ⚠ Never write using (true) — it exposes every row to everyone.betterThe with check clause stops a user updating their row to claim someone else's id. The comment names the single line that would undo everything: using (true).
What changed: RLS is deny-by-default, so the danger isn't forgetting to lock a table — it's a lazy policy like using (true) that quietly unlocks all of them.
The vague result is instructive precisely because it looks like nothing. Enabling RLS with no policy is a valid, complete SQL statement — it just denies everyone, so your app quietly stops returning data and you assume something else broke. The specific prompt adds the policies that let the right rows through.




