Guide · AI-built apps
Twelve things to check on an app built with Lovable, Bolt, Replit, Base44, v0 or Cursor, before real users and real data arrive.
AI app builders are very good at producing something that works when you click through it yourself. Security is about what happens when someone else clicks through it, or skips the clicking and talks to your database directly.
We build with AI every day, so this isn't a lecture about not using it. It's the list we work through when someone sends us an app they built with one of these tools and asks "is it safe?". You don't need to be a developer to do most of it. Where you do, the check tells you what to ask.
If you'd rather answer twelve quick questions and get a score, the AI app risk scorecard is the interactive version of this page.
Most of these tools put your data in Supabase or Firebase, and your app's front end talks to the database directly. The only thing standing between a visitor and every row in a table is the access rules. In Supabase that's Row Level Security (RLS). Supabase's own docs say a table in an exposed schema without RLS is readable and writable by any role with a grant on it.
How to checkIn Supabase, open the Security Advisor in the dashboard. An error called "RLS disabled in public" means a table is open. In Firebase, read your Firestore and Storage rules; the docs say never to use allow read, write: if true in production.
Every table has RLS on, with policies that say who can see and change which rows. More detail in our Supabase security guide.
Switching RLS on is half the job. A policy that says "everyone can read everything" passes the first check and protects nothing. The AI often writes these to make an error go away.
How to checkLook at each policy. Anything that reads using (true) for signed-out users, or checks only that someone is signed in, lets every user see every row. Supabase's advisor flags this as "Security policy allows unrestricted access".
Policies tie rows to their owner, for example a user only sees records where the user ID matches their own, and admin-only data is checked against a role stored where users can't edit it.
Supabase has two kinds of key. The publishable key (the old name was "anon") is meant to be public. The secret key (the old name was "service_role") bypasses every Row Level Security policy and must only ever live on a server. Payment, email and AI provider keys are secrets too.
How to checkSearch your code and your GitHub repository for service_role, sb_secret_ and the names of your payment and AI providers. Ask whoever built it where each key is stored.
Secrets live in the platform's secrets or environment settings and are only used in server-side functions. Any key that was ever exposed has been rotated, not just deleted from the code.
Authentication is where generated apps most often look finished and aren't: accounts that don't need a confirmed email, weak passwords allowed, or a reset flow that can be abused.
How to checkSign up with a fake address and see if you get straight in. Try a password like "password1". Check whether anyone can create an account when only invited people should.
Fixed looks likeEmail confirmation is on, a sensible minimum password length is set, new sign-ups are turned off if the app is invite-only, and leaked-password checking is on where your plan offers it.
Hiding the admin button from normal users isn't security. If the only check is in the page, anyone who finds the URL, or calls the database directly, gets admin powers.
How to checkLog in as an ordinary user and type the admin page address in directly. Ask: where is the "is this person an admin" decision made?
Fixed looks likeThe database rules and server functions check the user's role on every request, and the role is stored somewhere users can't change it themselves.
Edge functions and API routes often take a user ID, a price or a role straight from the request. Anything the browser sends can be changed by the person using it.
How to checkList your server functions. For each, ask: does it work out who the user is from their login, or from something they sent? Does it check they're allowed to do this?
Fixed looks likeFunctions identify the user from their verified session, recalculate prices on the server, and refuse anything the user isn't entitled to.
Uploaded files (ID documents, invoices, photos) often sit in a storage bucket. A public bucket is readable by anyone who has or guesses the link.
How to checkIn Supabase, open Storage and see which buckets are marked public. The Security Advisor also warns when a public bucket's contents can be listed.
Fixed looks likePrivate files are in private buckets, with storage policies limiting each user to their own files, and links that expire.
Without rate limits, a script can try thousands of passwords, send thousands of emails through your app, or run up your AI provider bill overnight.
How to checkLook for any limit on log-in attempts, form submissions and anything that calls a paid API. Check you have spending caps and alerts with your AI and email providers.
Fixed looks likeLimits on log-ins, sign-ups and expensive actions, and billing alerts set low enough that a bad night is an email, not a bill.
Your app is built on dozens of open-source packages. When one has a known security hole, everyone using the old version has it too.
How to checkLovable's quick security scan includes a dependency audit. On GitHub, Dependabot alerts do the same. Look for anything marked critical or high.
Fixed looks likeCritical and high alerts are dealt with, and someone checks again every month rather than once.
If someone deletes or encrypts your data, or a migration goes wrong, backups are the difference between a bad afternoon and closing the business. Supabase's free plan doesn't include daily backups; paid plans keep 7 to 30 days depending on tier.
How to checkFind out which plan you're on and where your backups are. Then ask when anyone last restored one somewhere safe to prove it works.
Fixed looks likeDaily backups, a copy kept outside the platform, and a test restore every quarter. Our guide on testing your backups walks through it.
Building against the live database means every AI-generated migration, every test record and every "let me just try this" happens to real customer data.
How to checkAsk: is there a separate project or branch for testing, with its own database and keys?
Fixed looks likeChanges are made and tried somewhere else first, and only then applied to live. You'd know if something went wrong because something is logging it.
It's common for the builder account, the database project, the domain or the GitHub repository to be in a freelancer's or a former employee's name. Then the security of your business depends on their password.
How to checkList every account the app needs (builder, Supabase or Firebase, hosting, domain, GitHub, payments, email, AI provider) and check whose name and email each is under, and whether two-factor login is on.
Fixed looks likeEvery account belongs to the business, two-factor login is on, and people who've left no longer have access.
Some of it. Use them; they're cheap and quick. Lovable has a quick security scan and a deeper one that reviews your code, and Supabase's Security Advisor catches open tables, risky policies and exposed functions. Lovable's own docs are honest that these tools "cannot guarantee complete security" and "do not replace a thorough security review".
What scanners are good at is the mechanical stuff: a table with no rules, a known-bad package, a key in the wrong place. What they're bad at is logic. A scanner can see that a policy exists. It can't tell that your policy lets one customer read another customer's invoices because the AI matched on the wrong column. Those are the holes that end up in the news.
We use our own scanning tools as a first pass on every app we review, then a person reads the rules, the functions and the flows. For anything holding sensitive data or under a contract that asks for it, we'd also recommend an independent penetration test, yearly for most businesses and quarterly where the data justifies it.
Don't start by asking the AI to fix it; you'll lose the evidence and probably not close the hole. In this order:
It can be, but not by default. Lovable apps usually store data in Supabase, so the safety of your data depends on the access rules on each table, where your secret keys are kept, and whether checks happen on the server. Run Lovable's security scan and Supabase's Security Advisor, then work through the checklist on this page.
Start with the database access rules, because that's where most exposures come from. Then move secret keys out of the browser, make sure admin and payment checks happen on the server, lock down file storage, add rate limits, set up backups you've tested, separate test from live, and make sure the business owns every account.
Yes. Lovable has built-in quick and deep security scans, Supabase has a Security Advisor, and GitHub flags vulnerable dependencies. They catch the mechanical problems well. They can't tell whether your rules match your business logic, which is where the serious holes tend to be, so treat them as a first pass rather than a sign-off.
A review of an app built mostly by an AI tool, by a developer who reads the code, database rules and server functions rather than just running a scanner. Ours covers security, database design, scalability and maintainability and ends in a written report with what to fix first. See our AI Code Audit.
Rotate every secret key and account password, take a copy of the database and logs before changing anything, close any obviously open tables or buckets, and work out whose data was exposed. If personal data was involved you may need to tell the ICO within 72 hours, so get advice quickly. Then fix the cause properly rather than asking the AI to patch it.
No scare stories. Plenty of AI-built apps are in decent shape and just need a few things tightened.
What we will cover:
Rather talk now? Book a call or ring 01474 639 089.
We reply within one working day.