Lovable app security checklist (from a security engineer)
By Pritesh Ghodge, security engineer · Last updated 25 October 2026
Want a quick outside check of your published Lovable app first?
Abbi Labs looks at your live site the way a stranger would: secret keys in the JavaScript, Supabase tables readable with your public key, exposed .env and .git files, and security headers. No sign-up for the quick check.
Weekly AI-app security checklist
One short email a week: a practical check for apps built with Supabase, Next.js and AI tools (RLS, leaked keys, headers and more). Unsubscribe anytime.
Lovable makes it possible to ship a real app in an afternoon. The security mistakes I see in Lovable apps are rarely exotic. They're the same handful: a table anyone can read, a key in the wrong place, an edge function that does whatever it's asked. This is the checklist I'd run before sharing a Lovable app with real users. Most items take a few minutes.
1. Run both of Lovable's built-in scans, and read the results
Credit where it's due: Lovable has real security tooling. Open your project's Security view. According to Lovable's docs:
- Quick scan runs automatically every time you publish. It checks database access rules (tables without row-level security, policies that let everyone through, leaked-password protection turned off), npm dependencies with known vulnerabilities, and MCP servers exposed without authentication.
- Deep scan is on demand. It reviews your code for users who can see or change data that isn't theirs, endpoints anyone can trigger, unsafe input, leaked secrets, payment bypasses and sign-in weaknesses.
Run the Deep scan before launch, fix every Critical, and don't dismiss a warning just because the AI says it's fine. What these scans review is your project: its code, dependencies and database settings. The rest of this list covers things worth confirming yourself, including how your published site looks from the outside.
2. Every Supabase table has RLS on, and policies check the user
Your Lovable app talks to Supabase with a publishable (anon) key that ships in the browser. That's by design. Row Level Security is what stops that key reading everything. Two traps:
- A table with RLS off is readable (and often writable) by anyone with the key.
- RLS on with a policy of
using (true)lets everyone through anyway. Policies should compare againstauth.uid().
The 60-second test, from any terminal (use your project URL and the publishable key from your app):
curl "https://YOUR-PROJECT.supabase.co/rest/v1/profiles?limit=1" \
-H "apikey: YOUR_PUBLISHABLE_KEY"An empty list or a permission error is good. A row of real data means anyone can read that table. Full walkthrough and fix SQL: how to check if your Supabase tables are readable by anyone.
Prompt for Lovable:
List every table in the public schema with: RLS on/off, and each
policy's command and USING / WITH CHECK expression. Flag any table
with RLS off and any policy using (true) for insert, update or delete.
Propose owner-only policies based on auth.uid(). Show me before applying.3. Views and default grants don't open a side door
A Postgres view runs with its owner's permissions unless told otherwise, so it can skip your RLS. And Supabase has historically granted the anon role select, insert, update and delete on new tables in public, which matters the moment a policy is missing or too loose. Since 30 October 2026 new tables need an explicit grant instead; if that now gives you a 42501 error, here's the safe way to fix it.
-- find views
select table_name from information_schema.views where table_schema = 'public';
-- make each one respect RLS (Postgres 15+)
alter view public.your_view set (security_invoker = true);
-- if logged-out visitors never write to a table, take that away
revoke insert, update, delete, truncate on public.your_table from anon;Click through your app afterwards: a public sign-up or contact form may rely on an anon insert.
4. Storage buckets holding user files are private
A public bucket serves any file to anyone who has (or guesses) the URL. Fine for logos and marketing images. Not fine for ID photos, invoices or anything users upload. In Supabase → Storage, make those buckets private, serve files through signed URLs, and add policies on storage.objects so users only reach their own folder.
5. No secret keys in the app's code
Lovable apps are built with Vite, so any variable starting with VITE_ is written into the JavaScript every visitor downloads. The Supabase URL and publishable key are meant to be there. These are not:
- Supabase
service_roleorsb_secret_keys (they bypass RLS entirely) - Stripe secret keys (
sk_live_,rk_live_) - OpenAI, Anthropic and other AI provider keys, email API keys, any database connection string
Check your published site, not just the editor: open it, then DevTools → Sources → search all files (Ctrl+Shift+F) for sk_live, sk-, service_role and sb_secret_. Secret keys belong in Supabase Edge Function secrets, called from a function. If one was ever in the bundle, revoke it with the provider first, then move it. More detail: VITE_ and NEXT_PUBLIC_ variables are shipped to every visitor, and if it was a Supabase secret key, do this in the next 15 minutes.
6. Edge functions check who's calling
Moving a key into an edge function protects the key, not your bill. A function that calls OpenAI, sends email or writes to the database for anyone who sends a request can be scripted. For each function:
- Require a signed-in user and get their id from the verified token, not from the request body.
- If the function uses the service_role key, it bypasses RLS, so it must do its own ownership checks.
- Add a per-user rate limit, and set a monthly budget in each paid provider's dashboard.
Review every Supabase Edge Function. For each, tell me: does it
require an authenticated user, does it trust any user id from the
request body, does it use the service_role key, and what stops one
user calling it 10,000 times? Fix the gaps and show me the diff.7. Your live site doesn't serve files it shouldn't
In a private window, open these on your published domain:
/.envand/.git/HEAD: you want a 404 or your normal app page.KEY=valuelines orref: refs/heads/mainmean they're public.- A
.js.mapnext to your main bundle: source maps can hand out your original source, comments included.
This matters most if you've exported the project and host it yourself. If .env was ever exposed, rotate every key in it. More detail, with curl tests and fixes for each: .env, .git and source maps on a live site.
8. Basic security headers on your domain
Check what your live domain actually sends, especially on a custom domain or self-hosted export:
curl -sI https://yourapp.com | grep -iE "content-security-policy|strict-transport|x-frame-options"Look for a Content-Security-Policy, Strict-Transport-Security (HSTS) and clickjacking protection (X-Frame-Options: DENY or CSP frame-ancestors). Missing headers are rarely the thing that gets you breached, but they limit the damage when something else goes wrong. How to add them, including on Lovable hosting: security headers for AI-built apps.
9. The two-account test (no scanner can do this for you)
Sign up as user A and user B. Logged in as B, try to open A's records: change an id in the URL, or replay a request from DevTools with A's id. If you can see or edit A's data, that's the bug, whatever any scan said. This is the check outside tools can't run, because it needs real accounts and knowledge of what each user should see.
Re-check after every publish
Most of these problems aren't there on launch day. They arrive later, in a "fix" for a permission error or a new feature built in a hurry. Lovable re-runs its Quick scan on publish. It's worth pairing that with an outside check of the live site, so you see what a stranger sees.
Let Abbi Labs check the outside for you
Abbi Labs scans your published app from the outside. The free quick check needs no sign-up: it reads your home page headers and its JavaScript for secret keys, tries /.env and /.git, and checks whether common Supabase tables return rows with your public key (it stores only a yes/no, never the data). Full scans, on domains you've verified you own, add public storage buckets and source maps, and Monitor re-scans weekly and after every deploy.
It can't do item 1 or item 9 for you: those need access to your project and real accounts.
FAQ
Is a Lovable app secure by default?
Lovable gives you good tools: a Quick scan that runs every time you publish and an on-demand Deep scan that reviews your code. But your app's security still depends on your database rules, where your keys live and what your edge functions allow. Lovable's own docs say the scans help but don't replace a security review, especially for apps handling sensitive data.
Is it safe that my Supabase key is visible in my Lovable app?
The publishable (anon) key is meant to be public, so yes, as long as Row Level Security is on for every table and your policies check who the user is. Secret keys (service_role or sb_secret_, Stripe secret keys, OpenAI keys) must never be in the app's code.
What does Lovable's security scan check?
Per Lovable's docs, the Quick scan checks database access rules (tables without RLS, policies that let everyone through, leaked-password protection turned off), known-vulnerable npm dependencies and unauthenticated MCP servers. The Deep scan reviews your code for access-control flaws, open endpoints, unsafe input, leaked secrets, payment bypasses and auth weaknesses.
Do I need to re-check after every publish?
Yes. Each change, including an AI 'fix' for an error, can loosen a policy, add a public variable or open an endpoint. Lovable re-runs its Quick scan on publish; it's worth also checking the live site from the outside after changes.
Does Abbi Labs work with Lovable apps?
Yes. Paste your published URL (lovable.app or your custom domain). The free quick check needs no sign-up and looks at your home page headers, its JavaScript for secret keys, /.env and /.git, and whether common Supabase tables return rows with your public key. Full scans on a domain you've verified you own add storage buckets and source maps.
Related guides
- OpenAI, Claude or Gemini API key exposed in your frontend? What to do now
- How to check if your Supabase tables are readable by anyone
- NEXT_PUBLIC_ and VITE_ variables are shipped to every visitor
- Supabase service_role key exposed? Do this in the next 15 minutes
- 3 files your production site shouldn't be serving: .env, .git and source maps
- Security headers for Lovable, Bolt, v0 and Cursor apps: CSP, HSTS and clickjacking
- Supabase "42501 permission denied for table": fix it with a GRANT, not by turning off RLS
- Is your Supabase storage bucket public? How to check it and lock it down