Is my Lovable app secure?

A plain-English guide for Lovable builders. Updated 13 October 2026.

Lovable builds a working app fast, but it builds what you ask for. If you never asked for the database to be locked down, or for a key to stay on the server, it may not be. The good news: the problems that matter most are few, well known and quick to fix once you know where to look.

This guide covers common security problems in apps built with Lovable, how to check for each one yourself, and a prompt you can paste into Lovable to fix it. You don’t need to code to follow it.

Why this matters

In 2025 security researchers checked 1,645 apps from Lovable’s public showcase and found 170 with database rules weak enough to expose data such as emails, names, phone numbers, payment and subscription records, and API keys. On one site they later showed they could also write to the database, marking themselves as paid. It was published as CVE-2025-48757 in May 2025. Lovable disputes that it was a flaw in Lovable itself, saying each customer is responsible for protecting their own app’s data. That is exactly the point: the rules are yours to get right, and the app works fine whether they are right or not, so you can’t tell by using it.

Lovable has since added its own security scan before you publish. Use it. Then get a second opinion from something that didn’t write the code.

1. Database tables anyone can read

Most Lovable apps keep their data in Supabase, either a Supabase project you connected or Lovable Cloud, which runs on Supabase. Your app talks to the database straight from the visitor’s browser using a public key. That key is meant to be public. What keeps your data safe is Row Level Security (RLS): rules on each table that say who may read or change which rows. A table with RLS off can be read by anyone who has the public key, which is anyone who opens your site.

How to check: on Lovable Cloud, open More, then Cloud, then Database, to see your tables and their security policies. If you connected your own Supabase project, open its Table Editor instead: tables without RLS are marked as unrestricted, and the Security Advisor lists them. Check that every table has RLS on and at least one policy that limits rows to their owner.

Prompt for Lovable:

Turn on Row Level Security for every table in the public schema. For each table, add policies so a signed-in user can only read, insert, update and delete their own rows (matching user_id to auth.uid()). Tables that really must be public should allow read only, never write. List every table and the policies you added.

Our guide to fixing Supabase RLS explains this step by step, with the SQL.

2. Policies that let everyone in anyway

RLS being on is not enough if the policy says yes to everyone. A policy with using (true) on a table of private data, or an update policy that lets a user change the user_id on a row, undoes the protection. So does a policy that checks a role stored in a column the user can edit themselves.

How to check: list every policy by running this in the SQL editor (in Lovable Cloud, or in your Supabase project):

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

For private tables, every policy should mention auth.uid(). Update policies should limit the new row to its owner too: any with check must be as strict as the using, and never with check (true).

3. The secret key in the browser

Supabase gives you two kinds of key. The public one (called anon or publishable) is safe in the browser. The secret one (service_role or a key starting sb_secret_) skips every RLS rule. If it ends up in your front-end code, anyone can copy it from your site and do anything to your database.

How to check: search your code on GitHub for service_role and sb_secret_. It should only ever appear in server code (an Edge Function in older Lovable apps, a server function in apps created since May 2026), read from a secret, never in code that runs in the browser.

Prompt for Lovable:

Check the whole project for the Supabase service role key or any sb_secret_ key. Remove it from all front-end code. Anything that needs admin access should move into server code (a server function, or an Edge Function in older projects) that reads the key from a secret and checks who is calling it.

4. Other keys bundled into the site

Lovable apps use Vite to build the part that runs in the browser, and any setting whose name starts with VITE_ is copied into the code every visitor downloads. That’s fine for public values. It is not fine for an OpenAI or Anthropic key, a Stripe secret key, or an email service key: anyone can copy them and spend your money.

How to check: look at every VITE_ setting. If losing it would cost you money or data, it doesn’t belong there. Also check old commits: a key you deleted is still in your git history, so rotate (replace) it with the service that issued it.

Prompt for Lovable:

Find every API key or secret used in the front end, including VITE_ variables. Move each private one into a secret and call it from a server function (or an Edge Function in older projects) instead. Tell me which keys I should rotate because they were exposed.

5. Server code that doesn’t check who is calling

Lovable puts server work (sending emails, calling AI, taking payments) in Edge Functions in older apps, and in server functions in apps created since May 2026. It runs with more power than the browser, so each one has to check that the caller is signed in and allowed to do that thing. A function that trusts a user ID sent from the browser lets anyone act as anyone.

How to check: for each server function or Edge Function, ask Lovable what it does if called by someone who is not signed in, or who sends another user’s ID.

Prompt for Lovable:

For every server function and Edge Function, verify the caller's JWT and take the user ID from the verified token, never from the request body. Reject calls that are not signed in, unless the function is meant to be public. Show me each function and what it now checks.

6. Payments you can get for free

If your app takes payments with Stripe, the moment a payment succeeds is usually a webhook: Stripe calls your app to say “this person paid”. If the webhook doesn’t check Stripe’s signature, anyone can send that message and unlock the paid plan. The same goes for apps that decide someone is “Pro” from a value the browser can change.

How to check: the webhook code should call Stripe’s signature check with your webhook signing secret. Who has paid should be stored where only the server can write it.

Prompt for Lovable:

Make the Stripe webhook verify the Stripe-Signature header with the webhook signing secret and reject anything that fails. Store subscription or payment status in a table users cannot write to, updated only by the webhook.

7. Admin pages that are only hidden

Hiding an admin button from normal users is not the same as stopping them. If the admin check happens only in the browser, anyone can reach the page or call the same database queries directly.

How to check: every admin action should be blocked by the database or the server, not just hidden in the interface. The admin role should live where users can’t edit it.

8. Files in public storage

Supabase Storage buckets can be public or private, and they have their own access rules. User uploads such as ID documents, invoices or private photos should be in a private bucket with rules that limit each file to its owner.

Questions

Is Lovable itself secure?

Lovable runs the platform, and it now scans apps before they publish. But the data rules, keys and checks inside your app are specific to your app, and they are your responsibility. A secure platform can still run an app with its database left open.

Is my Supabase anon key a secret?

No. The anon or publishable key is meant to be in the browser. It is safe only when Row Level Security is on for every table and the policies are right. The service role or secret key is the one that must never be in the browser.

Isn’t Lovable’s own security scan enough?

Use it: it catches real problems. A second, independent check is still worth having, in the same way you’d ask someone else to proofread your own writing. Holefind scans your git history for leaked keys, its full review reads all your code, and every finding points to the lines it found.