Lovable app security checklist before you launch

Eight checks to run on a Lovable app before you share the link — keys, Supabase tables, edge functions, headers, previews — with a prompt to fix what you find.

· 7 min read

The app works in the preview. You are about to post the link, invite your first users or point a custom domain at it. This is the cheapest moment to find security problems: there is no real data yet, nobody is relying on the app, and fixing a policy takes minutes instead of an incident.

This checklist is for a typical Lovable app: a React frontend talking to a Supabase backend (your own project or Lovable Cloud). Each item says what to look at, why it matters and how to fix it. Plan on about half an hour for the whole list.

Why Lovable apps fail in the same places

A Lovable app is split in two. The React code is compiled into JavaScript files that every visitor downloads. The database, auth and server functions live in Supabase. Almost every serious problem sits on the line between those two halves:

  • something secret ends up in the half that every visitor downloads;
  • the database trusts the browser more than it should;
  • a server function does the right work but never checks who is asking.

The AI builder is optimised to make the feature work. When a query fails because of a missing policy, the quickest way to make it work is a looser policy. When an API call needs a key, the quickest place to put it is next to the code that calls it. None of this shows up as an error, so it survives until someone looks.

Lovable does help. Its security scan runs a Quick scan every time you open the publish dialog — it covers database access rules, known npm vulnerabilities and unauthenticated MCP servers. A Deep scan, which you start yourself from the Security view, also reviews the code for leaked secrets, unauthenticated endpoints and access control. Use both. The checklist below covers the same ground from the outside, the way a stranger sees your live site, plus a few things a code scan does not look at.

Check it yourself: the launch checklist

1. Run the Deep scan and read every Critical

Open your project, go to the Security view and click Run deep scan. The Quick scan alone does not read your application code. Treat every Critical finding as a launch blocker. Do not click "fix all" and move on — open each finding, read what changed and make sure the app still works.

2. No secret keys in the bundle

Anything in your frontend code ships to every visitor. Search the project for these strings:

service_role
sb_secret_
sk_live_
sk-

Then check the live site, not just the code. Open it, then DevTools → Sources, and search all loaded files for the same strings. The Supabase anon or publishable key is supposed to be there; the service_role or sb_secret_ key is not. If you are unsure which one you are looking at, anon vs service_role explains how to tell them apart in under a minute.

Watch out for VITE_ variables. Lovable's Secrets documentation is explicit that values prefixed with VITE_ are exposed to the browser. A key named VITE_OPENAI_KEY is a public key, whatever you intended.

3. Every table has Row Level Security

The anon key is public, so Row Level Security (RLS) is the only thing deciding who can read which rows. In the Supabase SQL Editor:

select tablename, rowsecurity
from pg_tables
where schemaname = 'public'
order by rowsecurity, tablename;

Any row with rowsecurity = false can be read by anyone holding your public key. Then open Advisors → Security Advisor in the Supabase dashboard, which also catches views that bypass RLS. The full walkthrough, including how to test it as a stranger with curl, is in how to check if RLS is on.

4. Policies are not using (true)

RLS turned on with a policy that allows everyone is the same as RLS turned off. List your policies:

select tablename, policyname, roles, cmd, qual
from pg_policies
where schemaname = 'public';

Look for qual equal to true on tables that hold anything personal: profiles, orders, messages, uploads. Public data such as a product catalogue is fine; user data needs a condition like auth.uid() = user_id.

5. Edge functions check who is calling

Moving a call to an edge function hides the key, but the function itself is a public URL. Lovable's security best practices say to check the caller's identity in every server function, because clients can call it directly. Open each function in supabase/functions/ and look for a check near the top — typically supabase.auth.getUser() with a 401 response when there is no user. A function that sends email, calls a paid AI API or writes data without that check is an open door to your bill.

6. Storage buckets are not public by accident

In the Supabase dashboard open Storage and look at each bucket. A public bucket serves every file to anyone who has the URL. That is right for avatars and product images, and wrong for invoices, ID scans or user uploads. Private buckets need storage policies just like tables do.

7. Security headers on the live site

Run this against your live URL:

curl -sI https://your-app.lovable.app | grep -iE "strict-transport|content-security|x-frame|frame-ancestors|referrer-policy"

Missing Content-Security-Policy, HSTS or clickjacking protection is not an emergency the way a leaked key is, but it is worth knowing which ones your host sends. On a custom domain behind your own host or CDN you can usually add them yourself.

8. What search engines and link previews see

Open view-source:https://your-app.lovable.app. If the <title> is still the template's and there is no meta description, every shared link and search result shows that. This is not a security hole, but it is the first thing your first users notice. Edit index.html.

How to fix what you found

Fix in order of damage: secret keys first (rotate them in the provider's dashboard, then remove them from the code), then tables and policies, then edge functions, then storage, then headers and previews.

Give your AI builder a specific brief rather than "make it secure". A vague request tends to produce a confident summary and few real changes. Something like this works well in Lovable, Cursor or Claude Code:

Before I launch, go through this checklist and fix what fails.
Show me what you found for each item before changing anything.

1. Search the code for service_role, sb_secret_, sk_live_ and any
   secret in a VITE_ variable. Move every such call into a Supabase
   Edge Function that reads the key from Secrets. Tell me which keys
   I must rotate.
2. Enable Row Level Security on every table in the public schema.
   Users may read and change only rows where user_id = auth.uid().
   Anonymous users may read only these public tables: [list].
   Replace any policy that uses "true" on user data.
3. Set security_invoker = true on every view in the public schema.
4. In every Edge Function, call supabase.auth.getUser() first and
   return 401 if there is no user, unless I say the function is public.
5. Make every storage bucket private except: [list]. Add storage
   policies so users can access only their own files.
6. Set a real <title>, meta description and Open Graph tags in index.html.

Do not use the service_role key anywhere in client code.

Then go back through the checklist yourself. A fix is done when the check passes from the outside, not when the AI says it is done. Re-run the Deep scan as the last step.

Keep it from coming back

The checklist is a snapshot. Every Lovable prompt can rewrite half the app, and the next feature that needs a new table or a new API key can reintroduce exactly what you just fixed. Nothing in the app will tell you.

ScanYourSite runs the outside-in part of this list on your live site:

  • The free check searches every JavaScript file your site loads for Supabase service_role and sb_secret_ keys and other secret key formats, tells you which Supabase project the app talks to, checks security headers, and renders the page in a real browser to see the title, description and preview. Free covers one site, checked once a week, with fixes written out for three findings.
  • On Pro, after you verify the domain, it also takes the tables your site's code queries and asks Supabase, with your public key, how many rows a stranger could see. It counts rows and never reads their contents.
  • Pro ($19 a month, three sites) checks daily and after every deploy, and writes only when something new is wrong.

Whether you use a tool or a calendar reminder, the habit that matters is the same: run the checks again after every significant change, not only on launch day.

Check your own site in a minute

Free, no sign-up. You get a prioritised list of what’s wrong and a prompt you can paste back into Lovable, Bolt, Cursor or Claude Code.

Free, no sign-up. The basic check makes only the requests an ordinary browser would.

Lovable