1.The checklist in order
2.1. Set who can read and change each table
This step uses Supabase, which Lovable’s built-in backend is built on. Row level security (RLS) is a set of rules in the database that decide who may read and change each table’s rows. The public key in your page only reaches what RLS allows, and a table without RLS is readable and writable by anyone who has access to it, often signed-out visitors too.
- Write one line per table: who may read it, and who may change it.
- Compare with the rules: in Lovable, More → Database → Manage → Policies (Lovable); in your own Supabase project, the Security Advisor flags tables with RLS off and rules open to everyone (Supabase). On Base44, see Base44 app security.
- A rule for signed-out visitors (“anon”) with “using (true)” gives them every row. Keep it only for public data.
- Sign in as two test users and check that neither sees the other’s rows (how).
On Tidybook, anyone could read 12 review rows with emails and phone numbers, without signing in (critical). See what a stranger can see.
3.2. Keep secret keys out of the browser
Anyone can read what the browser downloads, so Lovable says secrets in frontend code should be considered compromised. A Supabase secret key (sb_secret_…, or the older service_role key) bypasses every RLS rule. Keys for paid services, such as a Stripe secret key (sk_live_…), belong in server code only (Lovable).
- Search your project’s code for sk_live_, sb_secret_, service_role and secret.
- A setting whose name starts with VITE_ is copied into the browser code; Supabase warns the same for NEXT_PUBLIC_. Never put a secret under such a name.
- Open your live app’s developer tools and search the downloaded files for the same words.
- If a secret key was ever public, rotate it: make a new key and switch the old one off.
The Supabase publishable key (sb_publishable_…, or the older anon key) is safe to expose; here is why. On Tidybook, the check found no secret keys.
4.3. Turn on email confirmation
Without email confirmation, anyone can sign up with an address they don’t own, and a bot can create many fake accounts that use your free limits.
- Lovable’s built-in backend: in More → Users → Settings → Email, turn off Auto-confirm email (Lovable).
- Your own Supabase project: turn on Confirm email in the email provider settings (Supabase).
- Test it: sign up with your own address. You should not get in before you click the emailed link.
On Tidybook, sign-up was open with no email confirmation, a high finding. More on sign-up without email confirmation.
5.4. Decide payments and paid features on the server
Users can inspect or change code that runs in their browser. If your page writes “paid”, “plan”, “credits” or “role” to the database, a user can too. Stripe says to fulfill orders in a server function started by a webhook (a message Stripe sends your server after a payment), since the customer may never reach your thank-you page.
- Ask your AI tool which code sets paid, plan, credits or role, and whether it runs in the browser or on the server.
- Move each such change into a server function that first checks the payment with Stripe.
- Check that a normal user cannot change those fields, even on their own row.
On Tidybook, a test user changed its own booking from “unpaid” to “paid” with one request, without paying (critical). More on paid features and admin rights for free.
6.5. Put a usage limit on any AI helper
Each call to an AI service costs you money. Without a limit, one bot can run up your bill.
- Let only signed-in users call the AI helper, through a server function.
- Count calls per user on the server and refuse calls over your limit.
- As a last guard, set a spend limit with the AI provider: OpenAI has a hard spend limit, and Anthropic a monthly spend limit.
On 31 October 2026, an earlier run of the deep checks called Tidybook’s AI helper 5 times in 3 seconds, without signing in. All 5 calls were answered (high). More on AI bill abuse.
7.6. Set rules for file uploads
If anyone can upload, a stranger can fill your storage at your cost. If a storage bucket (a folder for files) is public, anyone with a file’s link can open it.
- Keep buckets private, as Supabase does by default, unless every file is meant for everyone.
- Allow uploads only for signed-in users, into their own folder. Supabase allows no uploads without a rule; check that no rule lets everyone in.
- Set a maximum file size and the allowed file types on each bucket.
More on uploads at your cost.
8.7. Check admin pages on the server
Hiding the admin button does not protect the admin page: its address is in the code every visitor downloads (on Tidybook, /admin). The OWASP Top 10 list of web risks says access control only works in trusted server-side code.
9.8. Turn on browser protections
Security headers are settings your app sends to tell the browser what to block. A content security policy (CSP) mainly defends against cross-site scripting, where an attacker runs their own code in your page. Its frame-ancestors rule, or the X-Frame-Options header, stops other sites from showing your page inside theirs to trick users into clicks.
- Run Mozilla’s HTTP Observatory on your app’s address to see which headers are missing.
- Ask your AI tool or your host to add them, then run the test again.
Mozilla says a top grade does not mean a site is secure. Tidybook had no CSP and no framing protection (medium). More on security headers and CORS.
10.9. Run your builder’s own security scan
Lovable, Bolt and Base44 each have a built-in scan that reads your project from the inside.
- Lovable. The Quick scan runs each time you publish and checks your database rules and known flaws in your code packages. The Deep scan reviews all your code, including access control and payments; it is free, but you start it yourself in the Security view (Lovable).
- Bolt. Publish → Run security audit on paid plans; a database security check on all plans (Bolt).
- Base44. Dashboard → Security → Run Security Scan, on all plans (Base44).
What it cannot see: Lovable says its built-in scanners read your code and settings and do not replace a thorough security review. Testing the running app is a separate add-on billed by a partner. More on whether the builder’s scan is enough.
11.10. Check the live app from the outside
An outside check sees what a stranger sees: the code the browser downloads, and what your database and server answer to anyone. LidTight’s free check does this from your app’s link in seconds, with no sign-up. It looks for secret keys, tables and server addresses open to anyone, sign-up without email confirmation, secret files, public source code, and browser and email protections. It counts records and keeps no customer data.
What it cannot see: your server code and anything behind sign-in. For those, the free deep checks sign up two test users and test steps 1, 4, 5 and 6, plus admin rights from step 7. On Base44 apps, the sign-up check and the deep checks do not work yet.
Example: Tidybook, 1 November 2026
Tidybook is our demo app, built with Lovable. In 15.1 seconds, the free check and the deep checks found 2 critical, 1 high and 1 medium problem.
| Severity | What the check found | Step |
|---|---|---|
| Critical | Anyone can read your reviews table: 12 rows, with first_name, email, phone | 1 |
| Critical | An order in bookings can be marked as paid without payment (deep checks) | 4 |
| High | Anyone can create accounts without confirming an email | 3 |
| Medium | Some browser protections are switched off. Missing: content security policy, protection against framing | 8 |
They found no secret keys or secret files. A second test user could not see the first one’s booking, and the server blocked changes to another user’s data.
LidTight wrote this guide; every step except the last works without it. Run both scans again after each fix, and whenever you change sign-in or data access.