Lovable security
What does Lovable's security scan check, and what can it not see?
Lovable has two built-in scans. The Quick scan runs by itself every time you publish, takes about 10 seconds, and checks your live database's access rules (tables without row level security, rules that let everyone through, storage rules, leaked-password protection), your npm dependencies for critical vulnerabilities, and MCP servers your app exposes without sign-in. The Deep scan, which you start from the Security view, adds a review of all your application code: authorization, open endpoints, injection, secrets in code, payments and sign-in. Lovable's docs say both catch common issues but cannot guarantee complete security. Both look at the Lovable project, meaning the live database and the branch Lovable syncs; the docs do not say they read migration files before they run, or code on another branch or deployed elsewhere. Checked against Lovable's docs on 2026-10-24.

For the other Supabase security tools, grouped by the layer each one reads, see the Supabase security tools comparison.
Repository check
Check this in your repo
Check the GitHub repo of a Lovable app
For AI-built Vercel + Supabase apps, run the command below in a clone of your Lovable project's GitHub repo, with Node.js 20 or newer. It reads the branch you have checked out, before you merge. In supabase/migrations it reports a table created without RLS as rls_disabled, a policy using (true) as rls_policy_allows_all_read or rls_policy_allows_all_write, and a security definer function the anon key can call as security_definer_function_executable. In code it reports a Supabase service role key used in a browser file as service_role_key_in_client_code, Stripe with no webhook handler as missing_stripe_webhook, and env var names the code reads that no template lists as env_var_drift, which cannot see the secrets stored in Lovable, Supabase or Vercel.
It is a repository check, not a live database test: it does not connect to Lovable or Supabase, so it cannot see a policy changed in the dashboard, which the Quick scan can. It is advice, not a gate, and it exits with code 1 when it finds a blocker.
npx -y viberaven@1.6.12 checkWhat it printed on a Lovable-style fixture repo
On 2026-10-24 we ran it on a small fixture repo made for this page, not a customer repo, laid out like a Lovable export, with an admin page added in a local editor. The output is below, with the temp folder shortened to ~/lovable-app. It found three blockers, so the exit code was 1.
The secrets_in_repo note is about .env, which Lovable asks you to commit; its VITE_ values are public by design.
$ npx -y viberaven@1.6.12 check
viberaven check · ~/lovable-app
🔴 No RLS policy proof in migrations (rls_disabled)
1 public table without row level security: public.waitlist (supabase/migrations/20260920100000_waitlist.sql:1). The Data API does not enforce row restrictions for roles and operations allowed by the table's grants. Verify those grants to determine who can read or change rows.
🔴 A policy lets anyone write every row (rls_policy_allows_all_write)
Policy "Owners can update their listings" on public.listings (supabase/migrations/20260915090000_listings.sql:11) lets anyone, signed in or not, update every row, to any values: using (true). The name says "Owners can update their listings", but nothing in the policy checks who the caller is.
🔴 Service role key used in client code (service_role_key_in_client_code)
src/pages/Admin.tsx:5: creates a Supabase client with the service role key. This file ships to the browser, and the service role key skips RLS entirely. Move the call behind a server route or edge function and rotate the key.
🟡 Configuration filenames need review (secrets_in_repo)
This filename-only check found files not covered by .gitignore (.env). Contents and Git tracking were not checked by this finding. Base configuration may be intentionally tracked; credential content remains unverified.
🟡 A policy lets anyone read every row (rls_policy_allows_all_read)
Policy "Listings are viewable by everyone" on public.listings (supabase/migrations/20260915090000_listings.sql:9) lets anyone, signed in or not, read every row: using (true). Fine for truly public content; wrong for anything per-user.
🟡 Security definer function callable by the Data API roles (security_definer_function_executable)
public.has_role(uuid, public.app_role) at supabase/migrations/20260901120000_profiles_and_roles.sql:23 is security definer, so it runs with its owner's rights and RLS does not limit what it touches. No migration revokes EXECUTE from public, anon, authenticated, so anyone holding the anon key can call it at /rest/v1/rpc/has_role. If only the server calls it, add: revoke execute on function public.has_role(uuid, public.app_role) from public, anon, authenticated; Fix: revoke execute on function public.has_role(uuid, public.app_role) from public, anon, authenticated;
🟡 Stripe installed but no webhook handler (missing_stripe_webhook)
package.json lists stripe, but no webhook route or signature verification (constructEvent) was found. Payment state will silently drift from app state.
⚪ Env vars used in code but no env template documents them (env_var_drift)
Code reads 4 environment variables (STRIPE_SECRET_KEY, VITE_SUPABASE_PUBLISHABLE_KEY, VITE_SUPABASE_SERVICE_ROLE_KEY, VITE_SUPABASE_URL) and the repo has no .env.example, .env.sample or similar template, so a fresh clone or CI has no list of what to set.
⚪ No error monitoring detected (missing_monitoring)
No Sentry/PostHog (or similar) instrumentation was found. Production errors will only surface when users complain.
Verdict: ❌ 3 blockers, 4 warnings · score 5
Fix: viberaven fix · Details: ~/lovable-app/.viberaven/agent-tasklist.mdQuick scan vs Deep scan
The Quick scan (called the Basic scan until Lovable redesigned the Security view on 2026-09-23) is automatic: since 2026-06-01 it runs on every publish, and Lovable's docs say it does not cover application code. The Deep scan reviews all your code and includes the Quick scan's checks, but does not run on its own: start it from the Security view, where it usually takes 3 to 13 minutes.
Code changed outside Lovable
Commits pushed from Cursor, Claude Code or another editor reach Lovable only on the synced branch, where Lovable's docs say they go through the same checks as edits made in Lovable. A branch you have not merged is not in Lovable yet, so a check on the repo, in a pull request, is the one that sees it first.
What we found in 512 public Lovable repos
In the migrations of 512 public Lovable projects, 47.3% defined a security definer function the anon key can call, often a has_role helper like the one above. See In 47% of 512 Lovable Apps, the Anon Key Can Call a Security Definer Function. In the same repos, 16.2% had a policy that lets signed-out visitors update or delete a whole table and 10.4% created a table without RLS: We Read the Supabase Migrations of 512 Public Lovable Apps.
Checklist
Use both before you launch
- 01Resolve the Quick scan findings in the Security view.
- 02Run a Deep scan before launch and after a large change; it is the one that reads your app code.
- 03Turn on Block publishing with critical issues (all plans, off by default) if more than one person publishes. Lovable notes that passing it does not prove the app is secure.
- 04Clone the GitHub repo and check the migrations and code on the branch you are about to merge, including commits made outside Lovable.
- 05Sign in as two different users on the published app and confirm neither can read or change the other's rows. Lovable's docs say to test access rules yourself.
- 06On your own Supabase project, open its Security Advisor too.
Related
Related guides
Sources
Official docs behind this checklist
Browse all launch guides · Read resources · How to make and check your next change
FAQ
FAQ for builders before launch
Does the Lovable scan use the Supabase Security Advisor?
Lovable's docs do not say so. They call it a database review of your access rules and settings, run on Lovable Cloud and on your own Supabase project.
Is a clean Lovable scan enough to launch?
Lovable says no scanner catches every risk and suggests a professional review for apps with sensitive data. Treat a clean scan as one layer, and still test access as real users.