SCAN YOUR LOVABLE APP FOR VULNERABILITIES
ENTER YOUR LOVABLE APP URL
Enter your deployed app URL to check for security vulnerabilities.
Lovable turns a prompt into a deployed React frontend on top of a Supabase backend, live at a public URL in one session. It writes the tables, the auth wiring, the CRUD, and the Edge Functions for you. The problem is that “works” and “hardened” ship at the same moment: the app that renders correctly in the preview is the same app strangers can hit the second you share the link.
Lovable’s security model rests almost entirely on Supabase Row Level Security. The Supabase URL and anon key ship in the JavaScript bundle by design — that is not the vulnerability. The vulnerability is that the anon key becomes a read/write key for your whole database the moment any table is missing an RLS policy, and Lovable creates new tables as features are added without consistently protecting each one.
A black-box scan against the deployed URL is the only test that reflects what an attacker actually sees. It exercises the anon key against every exposed table, replays requests across user accounts, and reads the shipped bundle — none of which shows up in the Lovable editor.
Common vulnerabilities we find in Lovable apps
Missing Row Level Security on Supabase tables
Supabase exposes a PostgREST endpoint over every table. With RLS off, the anon key from your bundle can SELECT * FROM users straight from the network tab. Lovable’s AI adds tables as you add features but does not consistently attach policies, so an app that started secure regresses the moment you ask it to “add a comments table.” This is the recurring shape we see. Find the tables that slipped through, then enable RLS with a policy that matches your auth model; verify with the Supabase RLS Checker.
select tablename from pg_tables
where schemaname = 'public' and rowsecurity = false;
The anon key with no policy behind it
Because the anon key ships to the browser, its safety depends entirely on RLS being correct on every table it can reach. A single unprotected table turns that public key into full database access. Watch specifically for policies whose body is using (true) — Lovable sometimes “fixes” a broken query by re-opening the table that way. Reject any true policy unless the table is intentionally public.
BOLA / IDOR in generated CRUD
Generated resource endpoints filter by ID but skip the “does this user own this ID” check. Sign in as user B, take a request that returns your own record — a Supabase call with ?id=eq.<uuid> or a route like /api/projects/abc-123 — swap in user A’s ID, and refire. If A’s data comes back, that is a BOLA. Fix it with an RLS policy that scopes rows to the caller, or an explicit ownership check in the Edge Function.
create policy "owner read" on public.projects
for select using (auth.uid() = owner_id);
Service-role key bypassing RLS
Lovable sometimes generates an Edge Function or RPC that uses the service_role key to “make things easier.” Service role bypasses every RLS policy you wrote, so a lookup-by-ID inside that function returns whatever is asked for. Worse, the key sometimes lands in a chat transcript or a committed file. Create the function’s client with the request’s JWT (Authorization: req.headers.get('Authorization')) so RLS still applies, and rotate any service-role key that ever left Supabase.
Third-party keys in the client bundle
Vite inlines anything prefixed VITE_ into the JavaScript, so Stripe secret keys, OpenAI keys, and Resend keys wired into the frontend end up readable by anyone who views source. Harvesting bots find them within minutes of deploy. Anything other than the Supabase anon key and a publishable Stripe key belongs behind an Edge Function. Confirm with the Token Leak Checker.
Public storage buckets and unfiltered Realtime
The “let users upload an avatar” feature defaults to a public bucket — fine for avatars, dangerous for anything scoped to a user. Bucket privacy and policy enforcement are two separate switches, so a “private” bucket with no policy still lists and downloads. Likewise, a Realtime channel subscribed to a table with permissive RLS broadcasts every row change to every connected client. Scope buckets with per-owner storage policies and pin Realtime channels with a row filter.
How VibeEval works with Lovable
- Enter your deployed Lovable URL (
*.lovable.appor a custom domain). Optionally provide two test logins so the agent can run cross-user checks. - The agent drives a real browser through the app. It maps routes and Supabase calls, exercises the anon key against every reachable table, replays authenticated requests with a second user’s IDs to probe BOLA, reads the shipped bundle for leaked keys, checks security headers, and guesses storage-bucket paths.
- You get a report of findings ranked by severity, each with the concrete evidence (the table that answered anonymously, the ID that leaked another user’s row) and a paste-ready fix prompt — an RLS policy, an Edge Function change — you can feed straight back into Lovable.
Manual testing vs VibeEval
| Dimension | Manual review | VibeEval scan |
|---|---|---|
| Time per full pass | Hours across dashboard, bundle, and every route | Minutes against the deployed URL |
| Cross-user BOLA coverage | Tedious; needs two accounts and per-endpoint replay | Automated ID swap across every ID-keyed request |
| RLS coverage after a regeneration | Easy to forget the one table Lovable just changed | Every reachable table re-tested each run |
| Bundle key leaks | Manual grep, easy to miss rotated-in keys | Every deploy re-scanned |
| Business-logic flaws | Human judgment still required | Not a substitute — pairs with manual review |
| Repeatability | Depends on discipline after each prompt | Identical pass on demand |
Manual review still owns business logic and intent. The scanner wins on repeatability: every Lovable prompt can rewrite security-critical code, so the check that matters is the one you can run again in full after each edit.
Frequently asked questions
Does VibeEval work with custom domains?
Yes. VibeEval scans any deployed Lovable app whether it uses the default lovable.app subdomain or a custom domain.
Can VibeEval check my Supabase RLS policies?
The scanner does black-box RLS testing — it exercises the anon key against your tables the way an attacker would and reports which answer without authorization. For direct policy auditing against your schema, connect your Supabase project and use the Supabase RLS Checker.
Why scan if the app works in the Lovable preview?
The preview runs as you, authenticated, with data you own. It never tests what the anon key can reach, what a second user can read, or what ships in the public bundle. Those are exactly the gaps that reach production.
How often should I scan?
After every deploy, and specifically after any prompt that touched the database or an Edge Function. Lovable rewrites server code on each prompt, so a policy that passed yesterday can regress today.
Will scanning affect my production app?
No. VibeEval uses non-destructive probing — it reads and replays requests but never modifies or deletes data.
Related Lovable resources
- How to Secure Lovable — full hardening guide for the Supabase stack.
- Is Lovable Safe? — the three gaps in every Lovable app and how to fix each.
- Lovable Security Checklist — pre-launch checklist, critical-first.
- Is My Lovable App Secure? — a fast self-assessment.
- Lovable Tech Stack — what Lovable ships and where the seams are.
- Supabase RLS Checker — verify every table has a correct policy.
- BOLA in AI-Generated CRUD — the ownership-check failure in depth.
Test your Lovable app before launch
The gap between a working Lovable app and a hardened one ships to production in the same click. Scan the deployed URL before you share it — RLS coverage, the anon key’s reach, cross-user BOLA, and leaked bundle keys, in one pass.
SCAN YOUR APP
14-day trial. No card. Results in under 60 seconds.