VibeSecurity

Platform checklist

Securing an app built with Lovable: a review checklist

This is a checklist, not a tutorial. Work through it on your own Lovable project before you share the link or take real users. You will finish with a short written record of which areas you tested and what you saw.

By the VibeSecurity team6 min read

What Lovable typically generates and where the trust boundary is

Lovable projects are commonly a React and Vite single-page app that talks to a Supabase project for its database, authentication, file storage and serverless functions. Confirm the current stack in your own repository, because generated projects can differ and the product changes. Open package.json, look for a vite dependency and a Supabase client library, and note where the client is created.

The trust boundary in this layout is simple to state and easy to forget. Everything that ships to the browser is public: the JavaScript bundle, the Supabase project URL and the publishable (formerly anon) key. Supabase documents that key as safe to expose only because Row Level Security restricts what it can reach. The database policies and your server-side functions are therefore the real access control. The screens the assistant builds, including any admin page that is merely hidden, are presentation.

Lovable's own documentation describes built-in security checks and sensitive data scanning. It also states that these do not replace a thorough security review and cannot guarantee complete security, and that you are responsible for meeting the requirements of your use case. Read that as the vendor telling you this checklist is still your job.

The review checklist

Run every row against your own project and record the result.
AreaWhat to verifyHow to test on your own projectPass condition
Row Level SecurityEvery table in an exposed schema has RLS enabled.Run the tables query in the commands section in the Supabase SQL editor.No table holding user data shows rowsecurity as false.
Policy qualityEach policy ties rows to the signed-in user and is not simply true.Run the policies query and read the qual and with_check columns for each command.No policy on user data uses true, and write policies have a with_check.
Logged-out accessAn unauthenticated visitor cannot read or write private tables.Call the REST endpoint with only the publishable key using the curl example.Private tables return an empty list or an error, never other users' rows.
Cross-user accessUser A cannot read or change user B's rows by guessing an id.Create two test accounts, copy a row id from A, and request it while signed in as B.B gets nothing back and cannot update or delete the row.
Secrets in the bundleNo secret key, service role key or third-party secret ships to the browser.Build the project and grep the output folder for secret patterns.The grep returns no matches for secret-shaped strings.
Edge functionsEach function verifies the caller and derives the user id from the token.Call each function with no token, then with a token from another user.No token gives an authorization error and another user's token changes nothing of yours.
Storage bucketsBuckets holding user documents are private with per-user rules.Open a stored file URL in a private window while logged out.Private files are not retrievable without authorization.
Repository historyNo secret was ever committed, even if later deleted.Search git history for secret patterns with the pickaxe command.No hits, or every hit has been rotated.

Commands and queries to run

Run the first two in the Supabase SQL editor for your own project. The first lists whether RLS is on for each table in the public schema. The second lists every policy so you can read it in plain words.

Supabase SQL editor
select schemaname, tablename, rowsecurity
from pg_tables
where schemaname = 'public'
order by tablename;

select tablename, policyname, cmd, roles, qual, with_check
from pg_policies
where schemaname = 'public'
order by tablename, cmd;

Test as an outsider from your own terminal

Export your project URL and publishable key, then request a table with no user session. Replace the table name with one of yours. This tests only your own project.

An empty array for a private table is the pass result. A JSON array of real rows means an open policy. Adjust the grep patterns to the providers you actually use, and adjust dist if your build writes elsewhere.

Logged-out read test and bundle grep
export SUPABASE_URL="https://YOUR-PROJECT.supabase.co"
export PUBLISHABLE_KEY="your-publishable-or-anon-key"

curl -s "$SUPABASE_URL/rest/v1/YOUR_TABLE?select=*&limit=5" \
  -H "apikey: $PUBLISHABLE_KEY" \
  -H "Authorization: Bearer $PUBLISHABLE_KEY"

npm run build
grep -rEl "service_role|sb_secret_|sk_live_|BEGIN PRIVATE KEY" dist
git log --all -p -S"sk_live_" | head -50

Judging policies and functions

Supabase's documentation notes that when a request has no authenticated user, auth.uid() returns null, so a comparison like auth.uid() = user_id silently fails for anonymous requests. That is the behavior you want, but it also means a policy written the other way, or one that says using (true), can quietly expose every row. Read policies for each command separately: select, insert, update and delete each need their own answer.

For edge functions, look for three habits in the generated code. The function should verify the caller's JWT before privileged work. It should take the user id from the verified token, never from the request body. And any function that calls a paid third-party API should be limited in how often one user can trigger it. If a function uses a service role or secret key, it bypasses RLS entirely, so every check it performs must be written by hand.

Common mistakes with this workflow

  • Assuming the assistant's security scan means the project is safe. Lovable's docs say scanning does not replace a review.
  • Hiding an admin page in the interface and calling it protected. Only database rules and function checks count.
  • Putting a secret in a VITE_ variable. Vite documents that these values are bundled into client code and should not hold API keys.
  • Testing with one account. Bugs where users see each other's data only appear with two.
  • Asking the assistant to make an error go away by loosening a policy. Re-run the policies query after any fix that touches permissions.
  • Leaving test data, test accounts and open sign-up on the production project after launch.
  • Pasting real customer data into chat prompts or project files. Check the current documentation on data handling before you do.

Keep it working

Re-run the tables and policies queries after every change that adds a table, a bucket or a function. Repeat the two-account test before each release. Pass condition for the whole checklist: as a logged-out visitor you can read only intentionally public data, and as user B you can neither see nor change user A's rows.

Frequently asked questions

Is the Supabase publishable or anon key a leaked secret?

No. Supabase says publishable keys are low privilege and safe in client code because RLS limits what they reach. The dangerous keys are the secret and service role keys, which bypass RLS and must stay server-side. Your risk is missing or weak policies, not the public key itself.

Do Lovable's built-in security checks make my app safe to launch?

Lovable's documentation says the checks help reduce common risks but do not replace a thorough security review and cannot guarantee complete security. Use them as one input, then run the tests above yourself, especially if the app handles personal or payment data.

Should I test with real user data?

Use test accounts and dummy rows. The goal is to prove that isolation works, and you can do that with two invented users. Never run tests against a system you do not own.

How often should I repeat this checklist?

Repeat the database and function rows after any change that touches tables, storage, authentication or functions, and run the whole list before each public release. Large assistant edits can rewrite policies and functions without much notice.

Sources

  1. 1.Lovable docs: Built-in security checks
  2. 2.Lovable docs: Sensitive data scanning
  3. 3.Supabase docs: Row Level Security
  4. 4.Supabase docs: API keys
  5. 5.Vite docs: Env variables and modes