AI tools are good at making an app work. They are less reliable at making sure it only works for the right people. Before real people sign up or pay, go through this list. Each check says how to do it without reading code, and most take a few minutes.
It applies whether you built with Lovable, Bolt, Cursor, Replit, v0 or something else.
Keys and secrets
- No secret keys in the browser. Anything named
VITE_,NEXT_PUBLIC_,REACT_APP_orEXPO_PUBLIC_is sent to every visitor. Only public values belong there. AI, payment and email keys don’t. - No secret keys in your code or its history. Search your repo for words like
secret,sk_live,service_roleandapi_key. A key deleted in a later commit is still in your git history. - Rotate anything that was exposed. Removing a leaked key isn’t enough. Create a new one with the service that issued it and delete the old one.
- Your
.envfile is not in the repo. It should be listed in.gitignore.
Database
- Every table has access rules. On Supabase that means Row Level Security on every table, with policies that limit rows to their owner. See how to fix Supabase RLS.
- No “allow everyone” rules on private data. On Supabase, look for
using (true). On Firebase, look for rules that sayallow read, write: if true. - File uploads are private unless they’re meant to be public, and each file can only be read by its owner.
Logins and permissions
- The server checks who is asking. Every API route or server function that reads or changes private data should check the signed-in user itself, not trust a user ID sent from the browser.
- Admin really is admin-only. Hiding the admin button isn’t enough. The server or database must refuse admin actions from everyone else, and users must not be able to make themselves admin.
- Try it as someone else. Make two test accounts. Signed in as one, try opening the other’s pages by changing the ID in the address bar. You should get nothing.
- Password reset and sign-in links expire and can only be used once.
Payments
- The payment webhook checks the signature. With Stripe, your webhook should verify the
Stripe-Signatureheader using the signing secret. Without that, anyone can send a fake “paid” message. - Paid status is set only by the server. Whether someone is on a paid plan should never be a value the browser can change.
- Prices come from the server (or from Stripe), never from a value the browser sends.
What people can type in
- User text is shown as text, not run as code. If your app shows what users write (comments, profiles, notes), check it can’t include working HTML or scripts. In React, look for
dangerouslySetInnerHTML. - Database queries don’t glue in user input. Queries should pass values as parameters, not build SQL by adding strings together.
- AI features have limits. If your app calls an AI model, the key stays on the server, each user has a usage limit, and the app doesn’t blindly act on what the model says.
Site settings
- HTTPS everywhere, and plain http:// redirects to it.
- Security headers are set, such as Content-Security-Policy and Strict-Transport-Security. Most hosts let you add these in settings.
- CORS isn’t open to every site on APIs that use logins.
- Error messages don’t show internals such as stack traces, SQL or file paths.
- Dependencies are up to date, with no known critical vulnerabilities. GitHub’s Dependabot will tell you for free.
Just before you launch
- Run your builder’s own security scan if it has one (Lovable does) and fix what it finds.
- Get a second opinion from something that didn’t write the code.
- Have a privacy policy that says what data you keep and why, and a way for people to contact you.
- Know how you’d find out if something went wrong: error alerts, and a look at your database and payment logs in the first days.
Questions
Do I need a security audit before launching?
For most small apps, no. A professional security audit can cost thousands of pounds and usually takes days to arrange and carry out. Working through this checklist and getting an automated second opinion catches the common, serious problems. If you handle health, financial or children’s data, a professional audit is worth it.
Which of these matter most?
The database rules, secret keys and server-side permission checks. Those are the ones that let a stranger read or change other people’s data, and they are among the most common serious problems in apps built with AI tools.
Can my AI tool fix these for me?
Usually, yes, if you ask for the specific fix. A vague “make it secure” rarely works. Name the problem, for example “turn on Row Level Security for every table and limit rows to their owner”, then check the result.