Lovable is very good at the hardest part of building software: getting from an idea to a working app. Describe what you want, iterate in the chat, and within a few sessions you have real screens, real data, and real users clicking around. That used to be a six-month problem.
Production readiness is a separate, later problem — and it’s the one this checklist is about. Not because anything is wrong with what Lovable produced, but because “make it work” and “make it safe for strangers on the internet” are two different jobs, and only the first one is what you asked for while building.
This is a practical Lovable app security checklist you can work through before you ship — ten areas, each with something specific to look at and something specific to do. No security background required.
“The app works” and “the app is safe to launch” are different questions
When you test your own app, you use it correctly — logging in as yourself, clicking buttons in the intended order, typing sensible things into forms. Everything works, so the app is finished.
Someone using it incorrectly asks different questions. What happens if I change the ID in this URL? What’s at /admin? What comes back if I call this API endpoint with no login at all?
Those questions have answers whether or not you’ve asked them. And here’s what makes AI-assisted building genuinely different: a missing permission check doesn’t break anything. No error, no failing test — the feature works perfectly for everyone, including people who shouldn’t reach it. Working code and safe code look identical from the outside. So the pre-launch pass means walking the perimeter deliberately, once, before someone else does it for you.
Check for exposed API keys
Start here — fastest to check, most expensive to miss.
Lovable apps are built on Vite, so environment variables prefixed with VITE_ are compiled into the JavaScript bundle your browser downloads. That’s by design, but it means anything with that prefix is public and easy to find.
Some values belong there: your Supabase anon key, your Stripe publishable key. Others don’t — a Stripe secret key, an OpenAI key, an email provider key, a service-role database key. If one of those is in your frontend, anyone can spend your budget or read your data.
Check: search your deployed JS bundle for sk_, secret, and service_role. Then check your GitHub repo — including its history — for keys committed before you moved them to environment variables.
Fix: every secret belongs in a server-side edge function. Rotate anything that was ever exposed; deleting the line doesn’t invalidate the key.
Review authentication and role permissions
Authentication — who are you — is usually solid in a Lovable build. Authorization — are you allowed to do this specific thing — is where to look harder. The most common issue in any AI-built app is a page or query that confirms you’re logged in, then returns data without checking whose data it is.
Check: create two test accounts, log in as the first, find a URL or request containing an ID, and change it to one belonging to the second. If data comes back, that’s a launch blocker. Then check roles: if admin status lives in a field on the user’s own profile row, they can promote themselves.
Fix: enforce ownership and role checks in your Supabase policies and edge functions — server-side, where users can’t touch them. Hiding a button is good manners, not security.
Lock down admin routes
Most apps grow an admin area: a user list, a feature-flag toggle, a page for reading submissions. In a chat-built app those often arrive as ordinary routes with a link that’s merely hidden — and hiding a link doesn’t remove the route. Anyone who guesses /admin reaches the page.
Check: log out entirely and try every admin-ish path you can think of — /admin, /users, /settings, /debug. Watch for the page flashing its content before redirecting: that means the data was already fetched, so your API served it to a logged-out request.
Fix: the check has to happen where the data is served, not where it’s displayed. Delete admin pages you stopped using — the safest route is the one that doesn’t exist.
Validate form and user input
Every field where a user types something is a field where a user types something unexpected. React escapes text by default, which handles most cross-site scripting risk for free. The exception is wherever that default was turned off — usually dangerouslySetInnerHTML, added to make formatting render properly.
Check: search your code for dangerouslySetInnerHTML and ask, for each hit, whether the content comes from a user. Then test forms directly: paste 10,000 characters into a short input, and enter <script>alert(1)</script> into a bio to see whether it renders as text or executes.
Fix: validate on the server as well as in the browser. Client-side validation is a UX feature, bypassed by calling your API directly.
Check database rules and storage access
For most Lovable apps this is the security perimeter. Your Supabase row-level security policies decide who reads and writes what — and if RLS is off on a table, the anon key in your public bundle can read all of it.
Check: confirm RLS is enabled on every table holding user data, then read the policies. Anything with USING (true), or granting to anon or public, is open to the internet. Check storage buckets separately — uploads often land in a public bucket, fine for avatars and not for invoices or ID documents.
Fix: deny by default, then open only what a role needs. Verify by querying as an anonymous user; if rows come back that shouldn’t, the policy isn’t doing what you think.
Review third-party integrations
A shipped app is rarely just your app — it’s your app plus Stripe, an email provider, analytics, and whatever AI API powers your main feature.
Check: for each integration, ask what data it receives and what happens if its key leaks. Pay particular attention to webhooks: if Stripe calls your app to say a payment succeeded, your handler must verify the signature. Without it, anyone who knows the URL can POST a fake success event and unlock paid features for free.
Fix: verify every webhook signature, scope keys to the minimum they need, and route third-party calls through edge functions.
Scan dependencies
Your app pulls in a lot of packages, most of them dependencies of dependencies — code you never chose and have never looked at. Some carry published advisories.
Check: in your connected GitHub repo, run npm audit and read the output rather than the summary number. Enable Dependabot alerts while you’re there.
Fix: upgrade to patched releases, prioritising anything critical or high in a path reachable from user input.
Confirm production environment settings
The gap between “works in preview” and “safe in production” is mostly configuration.
Check: HTTPS enforced everywhere? Is your live site pointed at the production database, or still at the one full of test data? Rate limiting on login and password reset? When something errors, does the user see a friendly message or a raw database error naming your tables?
Fix: separate production from development properly — separate keys, database, and environment variables — and keep error detail in your logs rather than on screen.
Test payment and customer-data flows
If money or personal data is involved, test the unhappy paths too.
Check: what happens if a payment fails halfway? Can someone reach paid features without an active subscription — by navigating directly, or by keeping a session open after cancelling? Do card details stay entirely inside Stripe’s hosted checkout? What personal data do you store, and can you justify each field?
Fix: use hosted checkout so card data never reaches you, verify entitlements server-side on every request rather than trusting a flag set at purchase time, and delete what you don’t need.
Add proof customers can verify
The last item isn’t a vulnerability. It’s the question your first customers ask that your code can’t answer: why should I trust this? They can’t read your repo, and “built with AI” increasingly makes buyers cautious rather than impressed — particularly B2B buyers with a security questionnaire to fill in.
Check: is there anything on your site that lets a stranger confirm your app was reviewed by someone other than you?
Fix: independent verification, with a record they can open themselves. A verification app showing what was checked and when turns “we take security seriously” into something checkable. Self-assessment convinces nobody — that’s the whole reason third-party checks exist.
Five red flags
If any of these are true, get a second opinion before you launch rather than after.
You can’t explain how auth works in your own app. Not in detail — just at the level of “users only see their own records because of X.” If you can’t say what X is, nobody has confirmed it exists.
You haven’t reviewed your environment variables. Every one, checking which are exposed to the browser and which stay server-side. Ten minutes, and it’s where the most expensive mistakes live.
You have public admin routes. If you’ve never logged out and tried them, assume they’re public until proven otherwise.
You haven’t checked dependencies. An unrun npm audit isn’t a clean one.
You’re handling payments or customer data. A bug in a side project is a bug; the same bug in an app holding customer records is a breach, with disclosure obligations attached.
None of these mean your app is broken — only that there’s a specific unknown, and unknowns are cheaper to close before launch day than during it.
When to get a Lovable app independently checked
Working through this list yourself is worthwhile, and for a small internal tool it may be all you need. An independent check earns its place when the stakes change: you’re taking payments, storing personal or health data, selling to businesses who ask security questions, unable to audit the generated code yourself, or launching somewhere public enough that technically curious people will poke at it for fun.
We’ve written up the five risks we find in AI-built apps most often — secrets in repos, unguarded endpoints, unescaped input, stale dependencies, leaky errors. They appear regardless of which tool built the app, because they’re what a generator has no reason to add unless asked.
A LaunchSure check is a review against a published standard covering the ground in this checklist, done by someone with no stake in the answer. You get a plain-language report: each finding named without jargon, rated by severity, paired with a concrete fix — not a scanner dump. Read a sample report to see the format.
If your app passes, you get a credential with a valid-through date and a public record anyone can verify. There are a few LaunchSure tiers depending on how much assurance your customers need.
Before you ship
Lovable got you to a working app faster than any other route available, and the checklist above isn’t a knock on that — every app, hand-written or generated, ships with the same gap between working and launch-ready. Spend an afternoon walking the perimeter, fix what you find, then decide whether you want an independent pass on top.
Built your app with Lovable? LaunchSure can check it before you ship. Check my app and we’ll tell you exactly what we find.
Want proof your app is safe to ship?
Check my app