ShipSafe

Pre-launch · 8 min · Updated 26 Aug 2026

Is my Lovable app secure? How to check before you launch

The five questions to answer before you put a coding-agent app in front of real customers, and how to check each one yourself.

Lovable, Bolt, v0, Cursor and Claude Code let a small team ship a working product in days. The code that runs your login, your database rules and your API responses was written at speed, and most teams launch without anyone having read it for security.

"Is my Lovable app secure" does not have a yes-or-no answer, but it has five specific questions underneath it. Each one is checkable. This guide walks through all five and tells you which you can answer yourself and which need a login to test.

The short version

Roughly 1 in 10 apps built this way are in a secure state, and Veracode found about 45% of AI-generated code failing security tests. The exposure is normal, not a sign you did something wrong. What matters is checking before your first real customer does.

§ 01

Does authentication actually hold?

A coding agent will happily build a login screen that looks finished and gates nothing underneath. The screen hides the button; the server still answers the request. Signed-out access to a page you thought required login is the most common way this shows up.

Check it the way an attacker would: open your app, sign in, copy an authenticated URL like /dashboard or an API path like /api/orders, then open the same URL in a private window where you are signed out. If it returns data instead of sending you to the login, the gate is only in the UI.

What this becomes in a report

An endpoint that returns data to a signed-out request is a broken authentication finding. The evidence is the request with no session cookie and the response body that came back anyway.

§ 02

Can one customer read another's data?

This is the one that ends launches. If your app has accounts, the question is whether customer A can read customer B's rows. It usually breaks through predictable IDs: your own invoice is at /api/invoices/4821, so an attacker changes the number to 4822 and reads someone else's.

GET /api/invoices/4822 HTTP/1.1
Host: your-app.com
Cookie: session=<your own session>

HTTP/1.1 200 OK
{ "account": "someone-else", "amount_due": "$4,180" }
The test: change the ID in a URL you own to one you do not, while still logged in as yourself.

You can only test this properly with two accounts, because you have to prove that account A reached account B's data specifically. On Supabase this control is Row Level Security, which is off by default on every new table.

Related

If you use Supabase, read the Supabase RLS checklist. Row Level Security is the single control that decides this question.

§ 03

Does an endpoint return more than the screen shows?

Your profile page shows a name and an avatar. The API call behind it often returns the password hash, the Stripe customer ID, an internal role flag and every field on the row. The UI hides them; the response does not.

Open your browser's developer tools, go to the Network tab, reload a page, and read the JSON responses. If you see fields the screen never displays, every signed-in user can read them too.

§ 04

Is a secret key sitting in your JavaScript?

Anything your browser downloads is public, including your JavaScript bundle. Coding agents frequently paste a live API key straight into client code, or expose it through a mis-prefixed environment variable. A service-role database key or a secret payment key in the bundle is a direct path to your data.

Related

Full walkthrough: exposed API keys in your JavaScript bundle — how to search your own bundle and what each key type means.

§ 05

Is a storage bucket serving files without a signed URL?

Uploads are the quiet one. If your bucket is public, the URL to a user's uploaded file is often guessable or sequential, so anyone can walk through customer documents without logging in. The fix is signed URLs that expire, and a private bucket by default.

Test it by copying an upload URL from a signed-in session and opening it in a private window. If the file loads without a login, the bucket is public.

§ 06

A five-minute self-check

You can answer three of the five questions in a private browser window right now. The other two need a second account. Run through this before you launch:

  1. 01Open an authenticated page while signed out. It should send you to login, not return data.
  2. 02Change an ID in a URL or API path to one you do not own. You should get a 403 or 404, not someone else's row.
  3. 03Read the JSON in your Network tab. No password hashes, no role flags, no internal fields.
  4. 04Search your JavaScript bundle for key, secret and service_role. Nothing sensitive should match.
  5. 05Open an uploaded file's URL while signed out. It should not load.
Where a Preflight fits

The free Preflight answers the questions you can see from outside — secrets in the bundle, public files, transport and headers — in about a minute, with the evidence. The two account-to-account questions need a login, which is what the Launch Audit tests with your test accounts.

Questions people ask

Short answers, no hedging

Is a Lovable app secure by default?
No. Lovable produces an app that works, which is not the same as an app that holds. The controls that decide whether one customer can read another's data live in your database policies and your server-side ownership checks, and those are left to you. A generated app is a starting point, not a finished security posture.
How do I check whether my Lovable app is safe to launch?
Start from outside with what any visitor's browser can already reach: security headers, cookie flags, exposed .env or .git paths, source maps, and secret keys compiled into the JavaScript bundle. Then test the part a browser cannot see on its own, which is whether a logged-in account can retrieve a different account's records. The second half needs two real accounts and is where the serious findings are.
Can someone read my Supabase key out of a Lovable app?
Yes, and for the anon key that is by design. The anon key is meant to be public, so it is safe only if Row Level Security is enabled and scoped on every table it can reach. A service role key in the same bundle is a different matter: it bypasses all policies and must be rotated immediately and moved server-side.
Run the check on your own app

Stop reading about it. Point us at your URL.

The free Preflight is passive and read-only. It checks your app for exactly the exposures this guide describes and returns a score, a verdict and one finding with its evidence. No signup, no card.

Keep reading