Is Your Lovable App Secure? The Supabase RLS Checklist
Most Lovable apps ship with their Supabase database wide open because Row-Level Security is never enforced — here's how to check for it and lock it down.
You described your idea, Lovable generated a working app, and Supabase quietly gave you a real Postgres database behind it. It looks finished. But there's a gap that almost no vibe-coded app closes on its own: the database is very likely readable and writable by anyone who can reach your API. This isn't a Lovable bug or a Supabase bug — it's the default. AI-built apps ship insecure by default: roughly 91.5% carry at least one flaw, and while about 61% of AI-generated code is functionally correct, only around 10.5% passes a security review. The single most common way this bites Lovable founders is missing or broken Row-Level Security (RLS). This checklist explains why that happens, how to check your own app, and how to fix it.
Why the database is open by default
A Lovable app talks to Supabase directly from the browser using a public anon key. That key is meant to be public — it identifies your project, not a trusted server. The real gatekeeper is supposed to be Row-Level Security: Postgres policies that decide, row by row, who is allowed to see or change each record. When RLS is disabled on a table, or enabled with no policies (or a policy as permissive as 'using (true)'), the anon key can effectively query the whole table. Anyone who opens your app's network tab can copy that key and hit your Supabase REST endpoint directly — no login, no app UI, no rate limit on curiosity. Because the AI's job was to make the feature work, not to reason about who should be denied, RLS is the step that silently gets skipped. Escape.tech scanned 5,600 AI-built apps and found 2,038 critical vulnerabilities, 400+ exposed secrets, and 175 PII leaks — the shape of leaving the door open at scale.
How to check your own app in five minutes
You don't need to be a security engineer to find this. Open your Supabase project dashboard and go to the Table Editor or the Authentication → Policies view. Supabase visibly flags tables that have RLS turned off, and it shows you the list of policies on each table. Any table holding user data — profiles, orders, messages, uploads — that shows RLS disabled, or shows zero policies, is effectively public. A second, blunter test: while logged out of your app, try to load a page or trigger a request that reads data, and watch whether records still come back. If a signed-out visitor (or a different user's session) can pull rows that should be private, your policies aren't doing their job. Treat every table as guilty until you've seen its policies with your own eyes.
The RLS checklist: fix and verify
- Enable RLS on every table that holds user or business data — not just the obvious ones. A single forgotten table is the whole leak.
- Confirm each table has explicit policies. RLS enabled with zero policies denies everyone; that's safe but broken. RLS with a 'using (true)' policy allows everyone; that's open. You want neither.
- Scope read policies to ownership: a user should only select rows where the row's user/owner column matches their authenticated auth.uid(), not every row.
- Write separate, explicit policies for insert, update, and delete — read access is not write access. Make sure a user can't update or delete rows they don't own.
- Verify from the client side, not just the SQL editor. The SQL editor runs as an admin role that bypasses RLS, so it will look fine even when the public API is wide open. Test with a normal logged-in user and a logged-out session.
- Keep the service_role key strictly server-side (edge functions or a backend) and never in the browser bundle; only the anon key belongs in client code.
- Re-audit after every AI change. Regenerating a feature or adding a table can quietly reintroduce an unprotected table.
- Check storage buckets too: Supabase Storage has its own access rules, and a public bucket leaks files the same way an open table leaks rows.
RLS enabled with no policies is safe but broken; a 'using (true)' policy is broken and dangerous. Real security lives in the narrow space between the two — and that space has to be written, not generated.
This isn't only a Lovable problem
Every builder has a signature default failure. Lovable's is broken RLS. Bolt.new tends to hardcode secrets into the client bundle that ships to the browser. Cursor commonly produces broken object-level authorization (BOLA), where one user reads another's record just by changing an ID in the request. Replit deployments have exposed public .env files and secrets. v0 often leaves API routes unauthenticated. The pattern is the same everywhere: the AI optimizes for 'it works' and treats 'who is allowed' as someone else's job. With Lovable generating on the order of a million projects a week, the number of live apps sitting on an open database is not small — and the hard part was never shipping the demo. It's keeping the software alive: secured, deployed, and maintained.
Run the checklist above and you'll close the most dangerous gap in a typical Lovable app on your own. If you'd rather have senior software and security engineers audit, fix, secure, and ship it for you — including the RLS policies, the deploy, and the compliance basics like PDPL/GDPR — that done-for-you finishing is exactly what Comestare does.