Is your Lovable app secure? A 10-minute outside-in check
You built something in Lovable, it works, and you're about to share the link. Before you do, it's worth asking: what can a total stranger see and do with your live site?
Lovable does a lot to keep you safe while you build. But "safe while building" and "safe once it's on the internet" aren't quite the same thing. This guide covers what Lovable checks for you, what's still on you, and a 10-minute routine you can run on your own live site from a private browser window. No tools needed.
What Lovable already checks for you
Lovable has two built-in security scans, Quick scan and Deep scan, in each project's Security view. According to Lovable's docs, the Quick scan starts automatically when you open the Publish dialog. If it finds issues, you can open the Security view and run the Deep scan before you publish. Lovable also spots API keys pasted into the chat and steers you to store them in Secrets instead of hardcoding them, and it checks database access rules (row-level security) and dependencies. (Lovable docs: Security overview)
That's real protection, and you should use it. Lovable's docs also say it plainly: these tools "do not replace a thorough security review."
So run the Deep scan first. Then do the outside check below, because a few things only show up when you look at the deployed site the way a visitor does.
Step 1: Open your live site in a private window
Use an incognito/private window so you're not signed in. Everything below is what an anonymous visitor (or a bot) sees. Test your real published URL or custom domain, not the editor preview.
Step 2: Look for secret keys in your JavaScript
Your Lovable app's frontend runs in the browser, so every line of it is public. Lovable's docs say this too: API keys and secrets "cannot be stored safely in client-side code."
- Open DevTools (F12 or Cmd+Opt+I) and go to Sources (Chrome) or Debugger (Firefox).
- Press Ctrl+Shift+F (Cmd+Opt+F on Mac) to search across all loaded files.
- Search for each of these:
sb_secret_(a Supabase secret key)service_role(the legacy Supabase secret key)sk_live(a Stripe live secret key)sk-(common prefix for AI provider keys, e.g. OpenAI)
What's normal: a Supabase publishable key (sb_publishable_...) or the legacy anon key (a long string starting with eyJ). Supabase says publishable keys are "safe to expose online" because they only reach what Row Level Security allows. (Supabase docs: API keys)
What's not normal: any secret key. Supabase secret keys (and the legacy service_role key) bypass Row Level Security completely. If one is in your frontend, anyone can read and change your whole database.
If you find one: rotate it in the provider's dashboard first, then move the call that needs it into a Supabase Edge Function or another server-side spot, and store the key in Lovable Secrets.
Heads-up: Supabase says it's deprecating the legacy anon and service_role keys by the end of 2026 in favor of publishable and secret keys. Older Lovable projects may still use the legacy ones, so search for both.
Step 3: Check whether your Supabase tables are open
This is the big one for Lovable apps on Supabase. Supabase's docs put it directly: "A table in an exposed schema without RLS is readable and writable by any role with a grant on it." (Supabase docs: Row Level Security)
Two quick ways to check:
From inside Supabase (best): open your project in the Supabase dashboard and run the Security Advisor. It flags tables with RLS turned off and other risky settings. Supabase describes Advisors as "deterministic checks that ship with the platform." (Supabase docs: Advisors)
From outside (the visitor's view): while signed out, use your app normally and watch the Network tab. Requests to your-project.supabase.co/rest/v1/... show you which tables the page reads. If a signed-out request returns rows that should be private (other users' profiles, orders, messages), that table needs RLS and a proper policy.
The two-account test: sign up as user A and user B. As B, try to load A's data by changing an ID in the URL or in a request. You should get nothing back.
A policy that only lets people read their own rows looks like this (from Supabase's docs):
create policy "Users can view their own profile."
on profiles for select
to authenticated
using ( (select auth.uid()) = user_id );Watch for policies that say using (true). On a select policy that means "everyone can read this," which is fine for public content like blog posts but not for anything personal.
Step 4: Try the files that should never be public
In your private window, visit:
https://yourdomain.com/.envhttps://yourdomain.com/.git/HEADhttps://yourdomain.com/.git/config
You want a 404 (or your app's normal "not found" page). If you see text that looks like config or ref: refs/heads/main, your host is serving files it shouldn't. Fix your build or deploy settings before you share the link.
Step 5: Check your security headers
In DevTools, go to Network, reload, click the first request (your page), and look at Response Headers. The useful ones:
Strict-Transport-Security: tells browsers to always use HTTPS.Content-Security-Policy: limits which scripts can run on your page.X-Frame-Optionsor a CSPframe-ancestorsrule: stops other sites from framing yours (clickjacking).X-Content-Type-Options: nosniff.Referrer-Policy.
MDN has a plain explanation of each. (MDN: HTTP headers) Missing headers aren't an emergency the way a leaked key is, but they're cheap to add, and some, like HSTS and frame protection, close real attack paths. Where you set them depends on where you host. If you use a custom host, check its docs for "custom headers."
Step 6: Look at what you expose besides security
While you're in the private window:
- Admin pages: try
/adminand/dashboardwhile signed out. They should send you to log in, not show data. - Error pages: visit a URL that doesn't exist. You want a friendly 404, not a stack trace.
- Forms: submit your signup or contact form with nonsense. Does it validate? Does anything sensitive appear in the response in the Network tab?
A quick checklist you can copy
- Ran Lovable's Deep scan and fixed what it found
- No
sb_secret_,service_role,sk_liveorsk-in the JS bundle - Supabase Security Advisor shows no RLS errors
- Signed-out requests return no private rows
- User B can't see user A's data
/.envand/.git/HEADreturn 404- HSTS, CSP and frame protection headers present
/adminredirects to login; 404 page shows no stack trace
When to get an outside scan
The checklist above takes about 10 minutes and catches the mistakes that cause most of the embarrassing launch-day stories. If you'd rather have it run for you, along with checks for speed, search, broken links, email setup and accessibility, that's what we built PreFlight for. It looks at your live site the way any visitor could and runs 65 checks. The first scan of each site is free and shows how many checks you pass plus your top 3 fixes in full. If you want the full report, it's a one-time $19 (or $49 for 3 scans, $69 for 5), with a 14-day refund on unused scans.
Either way, do the private-window test before you post your link. It's the cheapest 10 minutes you'll spend on your launch.