DEV Community

Cover image for I've been scanning production Lovable apps for security issues. The same 5 problems show up every time.
Jace · Rivetz
Jace · Rivetz

Posted on • Originally published at rivetzco.com

I've been scanning production Lovable apps for security issues. The same 5 problems show up every time.

Martin Fowler published something today that I've been watching build for months.

His piece is called "The VibeSec Reckoning." The core thesis: telling an AI agent to be safe is not the same as enforcing that it is safe. Q1 2026 research puts it in numbers: 91.5% of AI-built apps have at least one critical vulnerability.

I started studying Lovable + Supabase apps specifically about three weeks ago. What I found wasn't surprising, but the consistency was.

The same five issues show up in almost every app I look at. Not because the builders are careless. Because the tools default to shipping code that works in demo and leaves production hardening to the developer, and most Lovable founders are non-technical.

Here's what I keep finding.

This one is the most expensive.

Lovable connects every app to Supabase using the anon key. The anon key is intentionally public — Supabase designed it that way. The security model assumes you've enabled Row-Level Security policies on every table.

Lovable doesn't enable it. RLS is off by default on every new Postgres table.

The attack is trivial:

curl -X GET \
"https://YOUR_PROJECT.supabase.co/rest/v1/users?select=*" \
-H "apikey: YOUR_ANON_KEY"
That returns every row of your users table. Unauthenticated. No login required.

CVE-2025-48757 documented this exact pattern hitting 170+ production Lovable apps. CVSS severity: 9.3 Critical.

How to check: Open your Supabase dashboard. Database → Tables. Look at the RLS column. If any table with private data shows "Disabled," you're vulnerable.

Full fix guide: Supabase RLS for Lovable Apps

If your app processes payments, Stripe sends events to your webhook endpoint when a payment succeeds. Your handler is supposed to verify that each event actually came from Stripe.

Most AI-generated webhook handlers skip this. They parse the JSON and trust it.

// What Lovable typically generates:
const event = JSON.parse(req.body)
if (event.type === 'checkout.session.completed') {
await fulfillOrder(event.data.object) // no verification
}
With this code, anyone who finds your webhook URL can POST a fake payment.succeeded event and trigger your fulfillment logic for free.

How to check: Search your codebase for constructEvent. If it's not there, signatures aren't being verified.

Full fix guide: Stripe Webhook Security for Lovable Apps

Right-click any deployed Lovable app. View Page Source. Press Cmd+F and search for sk_.

A surprising number return actual key values — Stripe secret keys, OpenAI keys, Supabase service_role keys — sitting in the JavaScript bundle visible to every visitor.

AI builders write functional code. Functional means the API call works. Nobody prompts them to move the key server-side. So it ends up in the React component, builds into the bundle, and ships to every browser.

The damage: anyone who finds your key can use it. Stripe secret keys can modify customers and issue refunds. OpenAI keys get charged to your account. Supabase service_role keys have full admin access to your entire database.

How to check: View Source on your deployed app. Search for sk_, sk-, service_role. If any of those return actual key strings (not just variable names), you have a leak. Rotate the keys immediately before fixing the code.

Full fix guide: Secrets Management for Lovable Apps

Most Lovable apps have at least one feature that calls an AI API — chat, generate, summarize, or similar. The endpoints powering those features rarely have any rate limiting.

No throttle per IP. No per-user cap. No global budget limit.

The attack: one user finds the endpoint and loops requests overnight. By morning, your OpenAI bill is $1,000-$5,000 depending on the model. The charges have already cleared.

while true; do
curl -X POST https://yourapp.com/api/chat \
-d '{"prompt": "..."}'
done
One script. Overnight. Done.

How to check: Hit your AI endpoint 50 times in rapid succession. If every request returns 200 OK with no throttling, you have no rate limiting.

Full fix guide: Rate Limiting for Lovable Apps

Lovable generates forms with client-side validation: required attributes, regex patterns, error messages. That's UX. It's not security.

The server-side handler typically trusts whatever JSON arrives. A curl request bypasses the form entirely.

curl -X POST https://yourapp.com/api/submit \
-H "Content-Type: application/json" \
-d '{"email": "alert(1)", "amount": -9999}'
If the server accepts that and writes it to your database, you have a problem.

How to check: Find any endpoint that writes to your database. Send a payload that fails the form's client-side rules directly via curl. If the server accepts it, validation is client-only.

These five issues aren't bugs. The AI didn't make a mistake. It generated exactly what you asked for, and what you asked for was "a working app." Production hardening (authentication enforcement, input validation, rate limiting, webhook security) requires a different kind of asking.

Most Lovable founders are non-technical. They don't know to ask for these things. And the free automated scanners don't find all of them. RLS edge cases, business logic exploits, and webhook verification require manual verification.

Most Lovable founders are non-technical. They don't know to ask for these things. And the free automated scanners don't find all of them — RLS edge cases, business logic exploits, and webhook verification require manual verification.

I built a free 5-minute self-check that walks through each of these in plain English, with exactly what to look for and what pass/fail looks like: rivetzco.com/self-check

No email required. If you find issues, the guides above have step-by-step fixes.

If you'd rather have someone go deeper — verifying the fixes are correct, checking the edge cases automated tools miss, and actually implementing the changes — that's what Rivetz does. Fixed price, async only.

Top comments (0)