Lovable security guide
How to secure a Lovable app's Supabase backend
Treat every table as public until a policy proves otherwise. Lovable ships your Supabase URL and publishable key in the client bundle, writes migrations to supabase/migrations/ and deploys edge functions for you. Read each migration for RLS, test policies as a real user, keep secret keys inside edge functions and run Lovable's Quick scan before every publish.
Last updated
Where does a Lovable app connect to Supabase?
Lovable's built-in backend, Lovable Cloud, is on by default. To use your own Supabase project, connect it from the editor. Lovable then writes SQL migrations, shows them to you for approval and saves them under supabase/migrations/. It also deploys edge functions and stores secrets in the Supabase project.
- Open Connectors > Supabase > Connect Supabase, or Settings > General > External Supabase > Connect.
- Sign in to Supabase and authorize Lovable for one organization.
- Pick the project. Use one Supabase project per Lovable project: Lovable's docs warn that projects sharing one Supabase project overwrite each other's secrets.
Which Lovable secrets reach the browser?
VITE_SUPABASE_URL and VITE_SUPABASE_PUBLISHABLE_KEY are frontend variables. Lovable embeds them in the client bundle at build time, which is fine for a publishable key. Keys for Stripe, Resend or LOVABLE_API_KEY belong in edge functions only. Search the build and the source for a secret key before you publish.
# Look for a secret key before you deploy. This must print nothing.
grep -rnE "sb_secret_|service_role" dist/ src/ 2>/dev/nullHow do I check the migrations Lovable writes?
Read each migration before you approve it. Every create table needs a matching enable row level security and at least one policy. After you apply the migration, run the catalog query below in the Supabase SQL editor.
# Migrations that create a table but never enable RLS.
for f in supabase/migrations/*.sql; do
grep -qi "create table" "$f" && ! grep -qi "enable row level security" "$f" && echo "$f"
done-- Tables in public without RLS. This must return no rows.
select c.relname
from pg_class c
join pg_namespace n on n.oid = c.relnamespace
where n.nspname = 'public' and c.relkind = 'r' and not c.relrowsecurity;alter table public.profiles enable row level security;
create policy "profiles: owner reads" on public.profiles
for select to authenticated
using ((select auth.uid()) = user_id);
create policy "profiles: owner inserts" on public.profiles
for insert to authenticated
with check ((select auth.uid()) = user_id);
create policy "profiles: owner updates" on public.profiles
for update to authenticated
using ((select auth.uid()) = user_id)
with check ((select auth.uid()) = user_id);How do I test that a Lovable policy checks ownership?
Lovable's checks report whether a policy exists. Prove what it allows: switch to the authenticated role inside a transaction, set a user's claims and count rows. Then list any policy that passes every row.
begin;
set local role authenticated;
select set_config('request.jwt.claims', '{"sub":"00000000-0000-0000-0000-000000000001","role":"authenticated"}', true);
select count(*) from public.profiles; -- only this user's rows
rollback;-- Policies that pass for every row.
select tablename, policyname, cmd, roles
from pg_policies
where schemaname = 'public'
and (qual = 'true' or with_check = 'true');Are Lovable edge functions safe to call from the browser?
Only if each function checks its caller. Lovable's docs say a client can still call server-side functions, and service-role code must check permissions itself. Supabase requires a valid JWT by default; verify_jwt = false lets anyone call the function.
- Read the caller's JWT and confirm the user may take the action before you touch the service role.
- Keep verify_jwt on for every function that is not a public webhook.
- Never return a secret, or a raw error that contains one, to the client.
# Functions that anyone can call without a signed-in user.
grep -n "verify_jwt = false" supabase/config.tomlWhat should I check before I publish a Lovable app?
- Open the publish dialog. The Quick scan runs on its own: database access rules, leaked-password protection, npm dependencies and an MCP check. Fix every finding.
- Run the Deep scan to review the application code.
- Run the RLS query above and the Supabase Security Advisor on the project.
- Add the optional Wiz or Aikido integration if your team uses them.
- After you publish, run the free /hack-me scan on your domain to find Supabase keys in public JavaScript.
Frequently asked questions
- Does Lovable write RLS policies for me?
- Lovable's docs do not say it writes policies on its own. They tell you to ask Lovable to review your policies and to verify them in Supabase. Lovable does run automated checks for RLS coverage after schema changes.
- Is the publishable key in my Lovable bundle a leak?
- No. Publishable keys are meant to be public and map to the anon or authenticated role. Escape.tech found anonymous JWTs in Lovable bundles tied to Supabase PostgREST APIs; the real question is what those keys can read, and RLS answers it.
- What happened with the Lovable app that exposed 18,697 records?
- In February 2026 researcher Taimur Khan reported 16 vulnerabilities, 6 critical, in an app on Lovable's Discover page, including inverted access-control logic in auth functions. Lovable said the app had code it did not generate, used a database Lovable did not host, and that acting on its pre-publish scan is the user's choice. Check auth logic too.