How to read an AI-built backend for security
You do not need to read code to spot the security gaps an AI builder leaves behind. Here is what to look at, what good and bad look like, and when to bring in an engineer.
Updated October 24, 2026: Tightened the short answers under the question headings.

As of October 15, 2026, you can learn a lot about whether an AI-built backend is safe without reading a single line of code, by checking its database rules, where its secret keys live and what its server checks.
The backend is the part a visitor never sees: the database that holds your users' data, the rules that decide who may read which rows, the secret keys that unlock paid services, and the server code that is supposed to check every request. An AI builder such as Lovable writes all of this, and insecure code works just as well as secure code, so the gaps do not show up until someone goes looking.
It is written for non-technical founders who built an app by prompting and now want to sanity-check it before, or just after, real users arrive. For each part of the backend you get a plain-English explanation, one concrete thing you can check yourself, what good and bad look like, and the point at which it needs an engineer. When a symptom has its own guide, this page gives the short version and links to it; the wider list of what goes wrong is in vibe coding security risks. Every platform fact is listed under Sources.
What counts as the backend, and why review it?
The backend is the database and the rules, keys and server code around it, and you review it because those rules, not the screens, keep one customer's data away from another. Most AI-built apps put the database close to the browser.
Lovable Cloud, for example, is built on Supabase, and the app's screens talk to that database using a publishable key that any visitor can read from the page. Supabase documents that key as safe to expose, because on its own it only reaches what the database's own rules allow. That is the whole reason this review matters: the rules inside the database, not the screens, keep one customer's data away from another. A screen that hides a record does nothing to stop someone asking the database directly.
So the review walks the backend in the order an attacker would: who can read which data, where the secret keys live, whether the server checks requests or trusts the browser, how roles work, how money is confirmed, and what happens when something breaks. The table below is the short version; the sections that follow tell you how to check each one.
| What to check | Good looks like | Bad looks like |
|---|---|---|
| Who can read which data | Row-level security on every table, each rule tied to the signed-in user | A table with no rules, or a rule that only checks that someone is signed in |
| Where secret keys live | Secret and payment keys only on the server | A secret key visible in the page's code or in the repository |
| Server checks vs trusting the browser | Prices, plans and roles decided by server code | The browser deciding what a user may do or pay |
| Sign-up, login and roles | Roles stored where users cannot edit them | An admin flag the browser can set |
| The payment webhook | Every payment event checked against Stripe's signature | Any request to the payment URL trusted as real |
| Errors and recovery | Daily backups, logs and a plan to restore | No backups, no logs, no way to notice a leak |
Who can read which data?
Each user should be able to read only their own data, and nobody else's. This is the first and most important question. You want a rule on every table that says a user may only read their own rows (row-level security, RLS).
Supabase is blunt about it: a table in an exposed schema without RLS is readable and writable by any role with a grant on it, so it tells you to enable RLS on every table. A rule that merely checks someone is signed in is not enough, because anyone can sign up. Supabase distinguishes the authenticated role (the user is signed in) from a rule that compares auth.uid() to the row's owner, and only the second keeps a stranger with a free account out of your data.
What you can check yourself: in Lovable, open More, then Database, then Manage, then Policies, and read each rule in plain English. A rule whose condition is simply true, or that never mentions the user's id, is a red flag. The surer test needs no code: sign up as two test users you own, create a record as the first, then sign in as the second in a private window and try to open the first user's record page by its address. If the second user sees it, data is leaking. If you confirm that, go straight to Lovable users can see each other's data, and for the rules themselves see Supabase RLS policy examples. When to get an engineer: the moment a two-account test shows a leak, or when you cannot tell which tables hold personal data.
Where do the secret keys live?
Secret keys belong only on the server, never in the page your visitors load. A secret key is any key that unlocks a paid or privileged service: the database's service key, your payment key, an AI provider key. The publishable key is fine in the browser, but the secret key is different.
Supabase says its secret key bypasses every row-level security policy you have and to never put one in a browser, a shipped application or source control. If one has leaked, deleting the line is not enough, because it stays in the history, so it has to be rotated at the provider.
What you can check yourself: run our free exposed key checker against your live site, which scans the code your app ships to the browser for key patterns. A clean result is good; any secret or service key it finds is a leak to close today, following exposed Lovable API key to rotate it safely. When to get an engineer: if a key was ever public, you need someone to rotate it and check your logs for whether it was used, not just remove it.
Does the server check, or does it trust the browser?
The server must check, and never simply trust the browser. Anything a user should not be able to decide for themselves, like a price, a plan, a usage limit or whether they are an admin, has to be enforced on the server.
Lovable's own security guidance says a function running on the server is still callable by a client, that code using the service role bypasses RLS and must check permissions itself, and that you should validate incoming data in server-side code and always treat client input as untrusted. The failure looks harmless because the normal screen never sends a bad value; the risk is that nothing stops a crafted request that does.
What you can check yourself: list the things a user should not control, then ask whether the app would still refuse each if the request came from outside your screens. You often cannot prove this from the dashboard alone, which is itself a sign it needs a technical check. The full pattern, with tests, is in vibe coding security risks. When to get an engineer: if the app sets prices, plans, credits or roles and you cannot see where that decision is enforced.
How do sign-up, login and roles work?
Logging in proves who someone is; it does not decide what they may do. The common mistake is treating a signed-in user as trusted, or keeping a role like admin where the browser can change it. Roles belong in the database, under the same row-level security as everything else, so users cannot promote themselves by editing a page value.
What you can check yourself: as one of your test users, look for any field that sets a role or a plan, and try to change it. A good app refuses; a bad one lets the browser decide. For how to set this up, see Lovable authentication and user roles. When to get an engineer: if admin or staff powers exist, or different users are meant to see different things, have the role checks reviewed before launch.
Is the payment webhook verified?
It has to be, because the payment webhook is a URL on the open internet that Stripe calls to say a payment succeeded, so your app can unlock the paid features. If you take money, the app almost certainly has one, and your code must confirm each message really came from Stripe.
Stripe is explicit: without verification, an attacker could send fake webhook events to your endpoint to trigger actions like fulfilling orders or granting account access, so always verify that events originate from Stripe before acting on them. It signs every event and shares a signing secret that starts with whsec_; your code checks the Stripe-Signature header against it and rejects anything that fails.
What you can check yourself: this is mostly a question for whoever set up payments. Ask it plainly: does the code that unlocks a paid plan check the Stripe signature, and where does the whsec_ signing secret live (it should be a server secret, never in the page)? A common visible symptom is a customer who paid but was not upgraded, covered in paid in Stripe but not upgraded. When to get an engineer: any time real cards are charged, have the signature check and the handling of duplicate events reviewed.
What happens on errors, and can you recover?
Something will go wrong, and whether you can recover depends on daily backups and a rehearsed way to restore. Backups are not automatic everywhere: Supabase automatically backs up all Pro, Team and Enterprise plan projects on a daily basis, and a free project gets none, so a free-tier app needs its own regular export.
Retention is limited too, at 7 days on Pro and 14 on Team, with Point-in-Time Recovery as a paid add-on.
What you can check yourself: find which Supabase plan your project is on and whether backups are enabled, and confirm you could answer "if the database was wiped tonight, what would we restore from?" A clear answer is good; a shrug is the gap. The full picture is in Supabase backups and disaster recovery. When to get an engineer: if you hold data you could not recreate, or data whose loss would trigger a legal duty, covered in which rules your product must meet.
How do you review it yourself, step by step?
Work through it in this order: make two test accounts and try to open one user's record as the other, read the RLS rules, scan your live site for exposed keys, ask whether the payment webhook checks Stripe's signature, confirm backups are on, then score the result with the free production-readiness check.
- 01Make two test accountsSign up as two users with email addresses you own. As the first, create one of everything the app stores: a profile, an order, a file.
- 02Try to cross the lineSign in as the second user in a private window and open the first user's record by its address. Seeing anything of theirs confirms the data is not protected at the database.
- 03Read the rulesIn Lovable, open More, Database, Manage, Policies. Flag any rule whose condition is true or that never mentions the user's id. On your own Supabase project, open the Security Advisor and read every finding.
- 04Scan for exposed keysRun the free exposed key checker on your live URL. Any secret or service key it finds must be rotated at the provider.
- 05Question the money pathAsk whoever set up payments whether the webhook checks Stripe's signature, and confirm an account unlocks only after payment.
- 06Confirm backups and logsCheck your Supabase plan, that backups are on, and that someone could restore after a mistake. A free project with no export is a gap.
- 07Score the whole thingRun the free production-readiness check to turn these into a score and the three things to fix first.
When should you get help?
Bring in an engineer when real customer data was exposed or might have been, when customers pay you or teams share data, when a two-account test keeps leaking after a fix, or when you cannot tell who wrote the rules. Doing the review tells you where you stand; it does not mean you must fix everything alone.
Our vibe-coding rescue service is built for exactly this: engineers find every path to the data, close it, and add the tests that keep it closed. If you are bringing on a developer anyway, handing an AI-built app to developers covers what to prepare.
Ongoing, a Plutonapps plan puts code review, security checks and tests on every change you prompt, so a new table never ships without its rules. Plans are on our pricing page.
Sources
Every platform fact above was checked against current documentation on October 15, 2026. Prices and plan limits were re-checked on October 22, 2026, and Lovable's menu paths on October 23, 2026. We review this page every 30 days.
- Supabase documentation: Row Level Security, on enabling RLS on every table, the authenticated role, and comparing auth.uid() to the row owner (supabase.com/docs/guides/database/postgres/row-level-security).
- Supabase documentation: API keys, on the publishable key being safe to expose and the secret key bypassing RLS and being refused in browsers (supabase.com/docs/guides/api/api-keys).
- Supabase documentation: Database backups, on daily backups for Pro, Team and Enterprise, retention of 7 and 14 days, and Point-in-Time Recovery (supabase.com/docs/guides/platform/backups).
- Lovable documentation: Security best practices, on the service role bypassing RLS, server functions being callable by clients, secrets never in frontend code, and validating client input on the server (docs.lovable.dev/tips-tricks/security-best-practices).
- Lovable documentation: Control who can access your app's data, on the Policies view under More, Database, Manage, checked October 23, 2026 (docs.lovable.dev/features/database-access).
- Stripe documentation: Receive Stripe events in your webhook endpoint, on verifying that events originate from Stripe, the whsec_ signing secret and the Stripe-Signature header (docs.stripe.com/webhooks).
Common questions
Do I need to read code to review an AI-built backend?
No. The most important checks are things you can see from the dashboard or prove with two test accounts: whether one user can reach another's data, whether a secret key is visible in the browser, whether roles can be changed from the page, and whether backups exist. Reading the code helps, but these gaps show up without it.
What is the single most important thing to check?
Whether every table has a rule tying each row to its owner (row-level security). Supabase says a table without it is readable and writable by anyone with a grant, and a rule that only checks a user is signed in is not enough, because anyone can sign up. Confirm it by signing in as a second test user and trying to open the first user's records.
How do I know if a secret key is exposed?
Run our free exposed key checker against your live site; it scans the code your app ships to the browser. The publishable key is meant to be public, but a secret or service key never should be. If one is found, rotate it at the provider, because deleting the line does not remove it from history.
Why does a payment webhook need to be verified?
Because the webhook URL is on the open internet, so without a check anyone could send a fake "payment succeeded" message and unlock paid features for free. Stripe signs every event and shares a signing secret; your code must verify the Stripe-Signature header before acting on the event.
When should I stop checking myself and call an engineer?
As soon as a two-account test shows a leak, if real customer data was or may have been exposed, if customers pay you or teams share data, or if the same problem returns after a fix. Our vibe-coding rescue service is built for that moment, and the free production-readiness check will tell you how exposed you are first.
More on this: Production architecture & security · Lovable app security checklist: is your app secure?
Built something in Lovable you want people to rely on?
We are the engineers who take it the rest of the way — secured, tested, released and supported.


