Apps built with AI
Is your AI-built app leaking data?
Short answer: if your Lovable, Bolt or v0 app uses Supabase, run four checks before real users arrive: row level security on every table, the service role key off the browser, sign-in links that return only to your domains, and a staging project apart from production.
Written by Matheus PavaneliPublished Oct 10, 2026Reviewed Oct 10, 20263 minPublic sources, linked
Download as Markdown0 of 4 checked
Mark each check as you go. Nothing is saved.
Why AI-built apps leak
Builders like Lovable, Bolt and v0 create the Supabase tables your app needs, but the rules that decide who may read each row are a separate step. The public key every browser receives can query the database directly, so a table without rules answers anyone who holds the key, signed in or not.
A visitor's browser
signed in as you@…, holding the public anon key
One request
GET /rest/v1/profiles with that key
profiles table
1,240 rows
- ana@… Ana Lima
- bo@… Bo Chen
- you@… You
- dev@… Dev Rao
1,240 rows come back to the browser, everyone's.
Switch to see what the rule changes. The rows are an example.
source: NVD
1. Row level security on every table, tied to the user
A table with row level security off, or with a policy that allows everyone, can be read in full with the public key.
Check it yourself
In the Supabase dashboard, open Authentication, then Policies. Every table in the public schema must show RLS enabled and a policy that compares a column with auth.uid().
Fix it
Turn RLS on for each table and write one policy per action. For a user's own rows:
alter table public.profiles enable row level security; create policy "own profile" on public.profiles for select using (auth.uid() = id);
2. The service role key never reaches the browser
The service role key skips every rule. If it ships in the front end, anyone can copy it from the page source.
Check it yourself
Open your live app, view the page source and search the scripts for service_role. Any key you find must carry the role anon.
Fix it
Keep the service role key only in server code or edge function secrets, generate a new one in the dashboard, then deploy again.
3. Sign-in links return only to your own domains
A wildcard in the redirect list lets a crafted sign-in link hand the session to someone else's site.
Check it yourself
Authentication, then URL Configuration. The list should hold your production domain and the exact preview domains you use, with no wildcard.
Fix it
Replace wildcards with exact addresses, and keep localhost only in the development project.
4. A staging project apart from production
Testing against the production database means one test or one prompt can change real customers' data.
Check it yourself
Check which Supabase project your preview builds point to. If it is the production address, they share data.
Fix it
Create a second project for staging, copy the schema with migrations, and point previews at it.
Questions
Is the anon key a secret?
No. It is meant to be public and ships with every page. The rules on each table, not the key, decide what a visitor can read.
Does Lovable add row level security for me?
Lovable's documentation asks you to review the policies of every table before going live. Treat the generated policies as a draft and check each table.
Can I run these checks without touching code?
Three of the four are in the Supabase dashboard. The service role check needs only the page source in your browser.