This isn't a general web-security article. Apps built with Lovable, Bolt, v0 and Cursor share an architecture, and that architecture produces the same handful of holes over and over.
The pattern: the AI builds a front end that talks to your database directly from the user's browser, using a public key that anyone can read in your page source. That key is meant to be public. What decides whether it's dangerous is a set of database rules — Row Level Security — that say who may read which rows. The AI wires everything up, the app works perfectly, your login screen appears, data shows up for the right users, and nothing errors.
That's the trap. The app looks completely fine from the outside. The login screen only exists in the browser, so anyone can skip it and query the database directly. Nothing warns you, because from the code's point of view nothing is wrong.
Everything below assumes no security background. If you can open your own website and right-click, you can do all of it.
Open your live app, right-click, View Page Source, and search for supabase.co. You'll find a project URL and a long anon key. Seeing them is normal — they're public by design.
Now open a private browser window, signed out, and ask the database for a table directly:
https://YOUR-PROJECT.supabase.co/rest/v1/users?select=*&apikey=YOUR_ANON_KEY
Try users, profiles, orders, messages, subscribers. An empty list [] or a permission error means the rules are working. If you see real rows, that table is readable by anyone on the internet right now — and has been since you launched.
The definitive version, if you have the Supabase SQL editor:
select tablename, rowsecurity from pg_tables where schemaname = 'public';
Anything with rowsecurity = false is open. Then check each enabled table actually has a policy — RLS switched on with no policy blocks everything including your own app, which is safe but broken, and people often switch it back off in frustration instead of adding the policy.
Open your live app, DevTools (F12) → Sources, and search all files for service_role, sk_live_, sk_test_ and OPENAI_API_KEY.
AI builders paste keys into client code more often than anyone would like. A Stripe secret key is spendable. An OpenAI key is billable. A Supabase service_role key bypasses every RLS policy you just checked in step one, which makes step one moot. If you find one: rotate it now, before fixing anything else, and move that work into a server function or Edge Function.
If your app calls a model through your own endpoint — something like /api/chat or /api/generate — open a private window, signed out, and call it directly with curl or the browser.
If it responds, it has no authentication. If it responds fifty times in a row, it has no rate limit either. Both together mean a stranger can point a script at your endpoint and run your model on your card. People almost always discover this from an invoice rather than from a scan, which is the expensive way round.
If your admin screens are shown or hidden by a flag in the browser, open DevTools and set it to true. Or find the admin URL and visit it directly while signed in as a normal user.
If an admin action then works, you don't have authorization — you have decoration. Hiding a button removes it from view, not from reach. Authorization has to be enforced by the database or a server function, where the user can't reach the switch.
Confirm the site loads over HTTPS and that http:// redirects to it. Check cookies are marked Secure and HttpOnly (DevTools → Application → Cookies). Check you have a Content-Security-Policy header.
Less dramatic than the first four, and easy to dismiss — but this layer is what stops a single cross-site scripting bug turning into a full account takeover. It's also the layer any customer's IT department will check first, so it's worth having in order before an enterprise buyer looks.
Before or after the manual checks, run whatever your builder gives you — it reads your source code, which the checks above cannot.
| Platform | What's built in |
|---|---|
| Lovable | Free Basic Scan (RLS policy linting, schema review, dependency audit) and Deep Scan (access control, unprotected backend endpoints, exposed secrets, unsafe input handling). Published apps also get a Trust Center at /.well-known/trust.html. Lovable states these "cannot guarantee complete security." |
| Bolt | A free security agent that runs on publish since 30 July 2026, covering access control, authentication, business logic, database policies, information disclosure, secrets and injection/XSS — and it writes and applies the fixes. |
| v0 / Cursor | No equivalent automatic pre-publish security scan at the time of writing. The checks above, plus an external scan of the deployed URL, are the practical route. |
These are good tools and you should use them. They also can't do two things: test the app as your users actually meet it, and be independent of the system that wrote the code. We compare the built-in scanners and an external scan in detail here, including where we come off worse.
Rather not do all five by hand? Broid runs every check on this page automatically and returns an A–F grade in seconds. Free, no signup.
Scan my app free →If you search for the price of a security audit you'll be quoted between $2,000 and $50,000. That's real, and it's for a human penetration test of a substantial application by a firm with liability insurance. It is not the right product for someone launching a side project this weekend, and the gap between "free checklist" and "$5,000 engagement" is where most solo builders simply give up and launch blind.
| Option | Cost | Right when |
|---|---|---|
| The checks on this page | Free, ~10 minutes | Always. Do these before anything else. |
| Your platform's built-in scan | Free | Always, if you have one. It reads code we can't see. |
| Automated external scan | Free grade; ~$1 or less for a full report | Before launch, after every significant change, and whenever a client asks. |
| Human penetration test | $2,000–$50,000 | You handle money, health data, or anything regulated. No automated tool of any kind replaces this. |
The reason the middle row can cost a dollar is that it is automated and narrow: it tests what your live app exposes publicly. That's a small, well-defined job — and it happens to be the job that catches the failures actually taking down AI-built apps.
Being straight about this, because plenty of tools aren't. An external scan tests what your app exposes to the internet. It will find readable tables, leaked keys, unprotected endpoints and missing protections. It cannot see your backend logic, and it does not log in — so it won't tell you whether one signed-in user can read another signed-in user's data through your own interface. It can't judge whether your business rules make sense.
A clean result means "nothing dangerous is exposed publicly, on the day we looked". It does not mean "this application is secure". Anyone who tells you a scan proves the second thing is selling you something. The same caution applies to a clean built-in scan, and to a clean bill from us.
It's the right question. The answer depends entirely on what the scanner does with it, so here is exactly what ours does — and you can verify every line from your own server logs.
anon key already in your page source. We never ask for a service-role key, a database password or a login.The stronger point: everything we do, an attacker can already do, and without asking permission. Your anon key is public, your endpoints are public, your bundle is public. A scan doesn't create the exposure — it tells you whether it exists before someone less friendly checks. And if you'd rather involve nobody at all, the manual steps above genuinely work. We published them for exactly that reason.
Apply the same caution to any tool that doesn't say what it does. Ask any scanner: which key do you use, do you read data or count it, do you write anything, and do you keep my report? If the answers aren't published, that's your answer.
About ten minutes for all five checks, most of it on check one. If you have three minutes, do check one — database exposure is the failure that ends companies, and it's the most common one in AI-built apps.
No. Every check is view-source, a URL in a private window, or a look in DevTools. If you built the app with an AI builder, you can do all of them.
No. In an AI-built app the login screen lives in the browser and the database is queried directly from the browser. Anyone can query the database without ever loading your login screen. Access control has to be enforced in the database, not in the interface.
Fix it before anything else. In Supabase, Authentication → Policies: enable RLS on that table and add a policy restricting rows to their owner, then re-test to confirm the data is no longer readable. If real user data was exposed, check whether your jurisdiction requires you to notify affected users — the PDPA in Singapore, the GDPR in the EU.
Before every launch, after every significant change, and periodically afterwards. Security isn't a state you reach, it's a state that drifts — a table added next month is outside today's clean result, and a policy disabled while debugging at 1am is the classic way a safe app becomes an exposed one.
For the grade and the list of problems, yes — ours is free and unlimited for that, and no signup is needed. What free scans generally don't include is the detail of each finding and a step-by-step fix. If you can act on a bare list, you never need to pay anyone.
A human penetration test runs $2,000–$50,000 and is the right answer if you handle money, health data or anything regulated. For a side project or an early SaaS, the manual checks above are free, your platform's built-in scan is free, and an automated external scan is free for a grade and around a dollar for a full report. The $2,000 quote and the $1 report are different products, not different qualities of the same one.
Paste your URL and get an A–F grade in seconds, including the live database-exposure test in check one.
Scan my app freeBroid is independent — we don't build apps, so we have no reason to tell you yours is fine.