Is my Lovable app secure?
Written by our founder, a cybersecurity architect · Updated
Short answer
Not automatically. Lovable writes working code fast, but whether your app is secure depends on a few things it can get wrong: your Supabase Row Level Security (RLS) rules, secret keys that end up in the browser, and backend functions that don’t check who is calling them.
Your Supabase anon key is visible to every visitor, and that is by design. What protects your data is RLS. If a table has RLS turned off, or a policy that allows everyone, anyone can download that table with the key your site already ships.
The checklist below covers what to check, in order of how much damage each mistake does. Most apps can be checked in under an hour.
Why do Lovable apps leak data?
A Lovable app is a React frontend that talks straight to Supabase from the browser. There is no server of yours in between, so every rule about who can read what has to live in the database itself, as RLS policies.
In 2025 a researcher found more than 170 apps built with Lovable whose databases could be read by anyone, including names, emails and payment details (CVE-2025-48757). The cause was the same in each: missing or overly broad RLS policies. Lovable has added security checks since, but your tables are still yours to verify.
The second common cause is secret keys. An OpenAI, Stripe or Supabase service_role key placed in frontend code, or in a variable starting with VITE_, is bundled into the JavaScript every visitor downloads.
1. Is RLS on for every table?
In Supabase, open Advisors → Security Advisor. Any table listed as “RLS disabled in public” can be read and changed by anyone who has your anon key. Turn it on:
alter table public.profiles enable row level security;With RLS on and no policy, nobody can read the table through the API. Then add policies for what each user should see. Our Supabase RLS guide shows how to check every table and test it the way an attacker would.
2. What do your policies allow?
RLS on is not enough if a policy lets everyone through. Look for these in Authentication → Policies:
using (true)on a table with personal data: every visitor can read every row.- Policies for
authenticatedusers with no ownership check. If sign-ups are open, anyone can create an account in seconds and read everything. - Insert or update policies without
with check: users can write rows that claim to belong to someone else.
A safe default for user data is “each user sees their own rows”:
create policy "Read own rows" on public.profiles
for select to authenticated
using ((select auth.uid()) = user_id);3. Are secret keys kept out of the browser?
Only two Supabase values belong in frontend code: the project URL and the anon (or publishable) key. Everything else is a secret:
- The Supabase
service_role(or secret) key. It ignores RLS entirely. - OpenAI, Anthropic and other AI provider keys. A leaked key gets used by strangers and billed to you.
- Stripe secret keys (
sk_live_…). Publishable keys (pk_live_…) are fine.
Put secrets in Supabase Edge Function secrets and call them from an edge function, never from the React code. If a secret was ever in your frontend or your Git history, rotate it: deleting the line does not remove it from old builds or commits.
4. Do your edge functions check the user?
Edge functions are your backend. Each one should answer three questions before doing anything: who is calling, are they allowed to touch this record, and how often can they call it.
- Read the user from the request’s
Authorizationheader withsupabase.auth.getUser(), and refuse the call if there is none. - When a function takes an id (an order, a document), check that the record belongs to that user.
- Functions that call an AI model cost you money on every call. Require a signed-in user and set a limit per user.
- Payment functions: compute the price on the server from your own product list, and verify the signature of Stripe webhooks.
5. Are storage and sign-ups locked down?
- Storage buckets marked public can be downloaded by anyone who has the file path. Fine for avatars, not for invoices or ID documents. Use a private bucket and signed URLs.
- Turn on email confirmation for sign-ups (Authentication → Providers → Email), so policies that trust any signed-in user don’t trust throwaway accounts.
6. What does your live site expose?
Finally, look at the deployed site the way a stranger would: keys inside the JavaScript bundle, source maps that reveal your source code, files like .env left public, and missing security headers.
Our free scan checks those in about a minute, with no account. It doesn’t test your database: Supabase tables readable without an account are checked by our backend checks after you prove you own the site, once a month on the free plan and weekly on Pro.
Checklist
- RLS is on for every table in the public schema
- No policy uses
using (true)on personal data - Policies check ownership, not just “signed in”
- Insert and update policies have
with check - No
service_role, AI or Stripe secret key in frontend code orVITE_variables - Keys that were ever exposed have been rotated
- Edge functions check the user and limit AI calls
- Prices are computed on the server; Stripe webhooks are verified
- Private files are in private buckets
- Email confirmation is on
Scan your site for free
Leaked API keys, exposed files and missing security headers, with a fix for each. No account, about a minute.
Questions
- Is it safe that my Supabase anon key is visible in my Lovable app?
- Yes, the anon key is meant to be public. It only gives the access your Row Level Security policies allow, so the policies are what you need to check.
- Does Lovable set up Row Level Security for me?
- Lovable usually creates policies when it creates tables, and it has security checks of its own, but it can still produce tables without RLS or policies that are too broad. Check each table yourself.
- Where should I put my OpenAI or Stripe secret key in a Lovable app?
- In Supabase Edge Function secrets, used from an edge function. Never in React code or in a variable starting with VITE_, which ends up in the browser.
- Can someone see my Lovable app’s source code?
- They can always read the JavaScript the browser downloads. If source maps are published, they can rebuild your original source too. That is why secrets must never be in frontend code.