Browse the blog
Sentrint Blog
Lovable · Checklist

A Lovable security checklist you can finish in an evening

Nine checks, in order of what actually gets people. Start with whether one user can read another user's data, because that is the flaw that shows up most and looks perfect when you only ever test your own account. Each check below names what to click and what a failure looks like.

This is the list to work through before real users touch your Lovable app. It is ordered by what actually causes damage, not by what is easiest to check.

You will need a second test account for the first one. Make it now.

1. Can one user read another user's data?

Why it is first: this is the flaw that shows up most often, and it is the one that looks perfect in testing. You only ever test as yourself, and as yourself everything behaves correctly.

How to check: log in as account A and note a URL with an id in it, something like /orders/1041. Log out, log in as account B, and paste that URL. Then do the same for the API calls you can see in the Network tab.

A failure looks like: account B seeing account A's data. Not an error page. The actual data, rendered normally.

Add authorisation checks so a user can only access their own records. For every route and every database query, verify the signed-in user's id matches the owner of the record before returning it. Do this on the server, not by hiding things in the UI. Return 404 rather than 403 for records that are not theirs. List every route that needs this and fix them.

2. Is RLS on, and are the grants revoked?

Why: RLS is off by default on a new Supabase table. Without it, anyone with your project URL can read the table, and your project URL is in your frontend code.

How to check: Supabase dashboard, table list, look at the RLS column.

The part most checklists miss: turning RLS on and adding a policy does not remove the privileges Supabase granted the table when it was created. Supabase's own documentation says adding policies does not take those grants back. You need revoke all on table <name> from anon, authenticated; as a separate step, then grant back only what the app uses.

We wrote that up properly in the four steps that actually close it. If you have already "done RLS" and stopped there, that page is the one to read next.

3. Are there API keys in your shipped JavaScript?

How to check: open your deployed app, open developer tools, and press Ctrl+Shift+F (Cmd+Shift+F on a Mac). That searches every loaded file, not just the page. Search for sk-, sk_live, secret and api_key.

A failure looks like: a match in a .js bundle. A Supabase publishable key is fine and expected. An OpenAI or Stripe secret key is an emergency.

If you find one, rotate it before you fix the code. The full version of this is in the API keys article.

4. Can your paywall be bypassed?

How to check: as a free account, open developer tools and look for premium features rendered in the DOM but hidden. Then call a premium API endpoint directly from the Network tab and see if it answers.

A failure looks like: the endpoint returning data. Or premium UI that appears when you delete a display:none.

Enforce subscription checks on the server for every premium endpoint. Do not render premium UI for free users at all rather than hiding it with CSS. Store subscription status in the database, never in local storage. Return 403 when a non-subscriber calls a premium route. Show me every premium feature and where its check is missing.

5. Is there a login on everything that needs one?

How to check: log out completely, then paste every admin or dashboard URL you know into the address bar. Include the ones you reach by clicking, not just the ones in the nav.

A failure looks like: the page loading. Also worth checking: the page redirecting you to login while the API call underneath it still returns data. Look at the Network tab, not the screen.

6. Does a script survive being typed into a form?

How to check: find a field whose contents another user will see, a comment, a display name, a bio. Enter <script>alert(1)</script>, save, and view it as the other account.

A failure looks like: an alert box. If you see one, anything that field can hold runs in your users' browsers.

Sanitise all user input that is stored and later displayed. Escape HTML on output, or use a sanitiser like DOMPurify for fields that must allow formatting. Validate on the server, not only in the browser. Show me every field that is stored and rendered back to a user.

7. Is rate limiting on the routes that need it?

How to check: try your own login with the wrong password twenty times quickly. Then submit a signup form ten times.

A failure looks like: nothing slowing down or blocking you.

Why it matters more than it sounds: without a limit, an attacker can try tens of thousands of passwords an hour against your users. With one, the same attack takes years.

8. Do your error messages give things away?

How to check: break things on purpose. Submit garbage to a form, visit a URL that does not exist, log in with an email that has no account.

A failure looks like: a stack trace, a file path, a database error, or a login that says "no account with that email" (which tells an attacker which addresses are worth attacking).

9. Do you know what you would do if it happened?

How to check: ask yourself where you would take the app offline, who you would email, and how you would reach your users.

There is no prompt for this one. Write four lines in a note: how to take the site down, your hosting provider's security contact, where your backups are, and a draft of the email you would have to send. Four lines is not an incident response plan and it is infinitely better than nothing at two in the morning.

What this checklist does not cover

A checklist finds what it lists, and only where it points. That is a description of the format rather than a complaint about it.

The nine above are the common ones because they are the ones people know to look for. The flaw that gets exploited is usually in the file nobody thought to open, in a route added three weeks after launch, in the second admin page you forgot existed.

That is the argument for having something read the whole repository rather than a list you work through by hand. Sentrint does that: every file, in plain English, with a fix prompt written for Lovable specifically. A code scan, not a pentest, and the first one is free with no card.

Work through the nine either way. Numbers one, two and three are most of your risk, and you can finish them tonight.

More on Lovable
Enough reading. See your own findings.
A free scan turns this into a list of what to fix, in order.
Run your free scan