Lovable Security Vulnerabilities 2026: Exposed Keys, Missing RLS, and What Audits Catch
I spent the last three months auditing apps that clients brought to us after building their MVPs on Lovable. The pattern is so consistent it's almost boring: exposed Supabase service keys in client bundles, zero RLS policies, hardcoded OpenAI and Stripe secrets sitting right there in the JavaScript for anyone with DevTools to grab. Every single time.
This isn't a hit piece on Lovable. The platform is genuinely impressive for prototyping. But there's a canyon-sized gap between "working demo" and "production-ready application," and Lovable doesn't tell you about most of what's sitting in that canyon. A community researcher audited 50 AI-built apps and found the same five security mistakes in nearly all of them. Another developer scanned 200+ vibe-coded sites and found an average security score of 52 out of 100 -- with the worst offenders concentrated in Lovable + Supabase applications specifically.
Let's walk through every vulnerability we keep finding, why Lovable's own tooling misses them, and exactly how to fix each one.
Table of Contents
- The Architecture That Creates the Problem
- Vulnerability 1: Exposed Supabase Keys in Client Code
- Vulnerability 2: Missing or Broken RLS Policies
- Vulnerability 3: Hardcoded Third-Party API Secrets
- Vulnerability 4: Missing Security Headers
- Vulnerability 5: No Input Validation or Sanitization
- What Lovable's Built-In Security Scan Actually Checks
- What a Production Audit Catches That the Platform Doesn't
- The Moltbook Incident: A Real-World Case Study
- How to Fix a Lovable App Before Going to Production
- Tools for Automated Scanning
- FAQ

The Architecture That Creates the Problem
To understand why Lovable apps are disproportionately affected, you need to understand the architecture. Lovable exclusively uses Supabase as its backend. There's no Firebase option, no custom backend, no escape hatch. When you build something in Lovable, it generates a React frontend that talks directly to Supabase's REST API using the client library.
Supabase is designed so that the anon key is safe to expose publicly -- it's essentially a project identifier. The security model relies entirely on Row Level Security (RLS) policies at the PostgreSQL level. Think of it this way:
| Component | Meant to be public? | What protects you |
|---|---|---|
| Supabase URL | Yes | Nothing needed -- it's just a URL |
anon key |
Yes | RLS policies on every table |
service_role key |
Absolutely not | Must stay server-side only |
| Database connection string | No | Never expose to clients |
The problem is that Lovable's AI generates code that often treats all of these the same way. It puts the anon key in the frontend (fine), but then creates tables without enabling RLS (catastrophic). Sometimes it puts the service_role key in client code too (game over). As one developer on Reddit put it: "AI does what you ask. It just never thinks about what you didn't ask."
Vulnerability 1: Exposed Supabase Keys in Client Code
Every Lovable app initializes the Supabase client something like this:
// src/integrations/supabase/client.ts
import { createClient } from '@supabase/supabase-js'
const supabaseUrl = 'https://xyzcompany.supabase.co'
const supabaseAnonKey = 'eyJhbGciOiJIUzI1NiIs...'
export const supabase = createClient(supabaseUrl, supabaseAnonKey)
The anon key being here is fine -- that's by design. The problem comes in two forms:
The `service_role` Key Leak
We've seen Lovable-generated code where the service_role key ends up in client-side code, usually because someone prompted the AI with something like "make this work even though RLS is blocking it." The AI's solution? Use the admin key. The service_role key bypasses all RLS policies completely. If it's in your frontend bundle, anyone can extract it and have full read/write access to your entire database.
The `.env` File Committed to Git
Lovable projects deployed to GitHub frequently have .env files committed to the repository. Even if the repo is private now, if it was ever public -- even for a minute -- those keys are compromised. Bots scrape GitHub constantly for exactly this pattern.
How to check:
# Search your codebase for service_role keys
grep -r "service_role" --include="*.ts" --include="*.tsx" --include="*.js" --include="*.env" .
# Check git history for accidentally committed secrets
git log --all -p -- '*.env'
How to fix: Remove the service_role key from all client code immediately. Rotate the key in your Supabase dashboard (Settings → API). Use the key only in server-side code -- Supabase Edge Functions, a Next.js API route, or a separate backend.
Vulnerability 2: Missing or Broken RLS Policies
This is the big one. CVE-2025-48757 exposed 303 vulnerable endpoints across 170+ Lovable-built apps. According to Escape.tech, 83% of exposed Supabase databases involve RLS misconfigurations.
Here's what happens by default when Lovable creates a table:
-- What Lovable often generates
CREATE TABLE user_profiles (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
user_id UUID REFERENCES auth.users(id),
full_name TEXT,
email TEXT,
created_at TIMESTAMPTZ DEFAULT now()
);
-- Notice what's missing? RLS isn't enabled.
-- This table is fully readable and writable by anyone with the anon key.
Without RLS, your Supabase database is essentially a public API. Anyone who knows your project URL and anon key -- both of which are in your frontend code -- can do this:
// An attacker's browser console
const { data } = await supabase.from('user_profiles').select('*')
// Returns EVERY user's data
await supabase.from('user_profiles').delete().neq('id', '')
// Deletes everything
Three Flavors of RLS Failure
| Failure Mode | What Happens | Severity |
|---|---|---|
| RLS not enabled at all | Complete public read/write access | Critical |
| RLS enabled but no policies defined | Nobody can access anything (app breaks) | High (forces devs to disable RLS) |
Overly permissive policies (e.g., USING (true)) |
Looks secure, actually isn't | High |
The third one is particularly insidious. We've seen Lovable generate policies like this when prompted to "fix the permissions":
CREATE POLICY "Allow all access" ON user_profiles
FOR ALL
USING (true)
WITH CHECK (true);
This is RLS theater. It's enabled, it has a policy, and it does absolutely nothing.
What a proper policy looks like:
-- Enable RLS
ALTER TABLE user_profiles ENABLE ROW LEVEL SECURITY;
-- Users can only read their own profile
CREATE POLICY "Users read own profile" ON user_profiles
FOR SELECT
USING (auth.uid() = user_id);
-- Users can only update their own profile
CREATE POLICY "Users update own profile" ON user_profiles
FOR UPDATE
USING (auth.uid() = user_id)
WITH CHECK (auth.uid() = user_id);
-- Only authenticated users can insert, and only for themselves
CREATE POLICY "Users insert own profile" ON user_profiles
FOR INSERT
WITH CHECK (auth.uid() = user_id);

Vulnerability 3: Hardcoded Third-Party API Secrets
This one makes me wince every time. We regularly find OpenAI API keys (sk-...), Stripe secret keys (sk_live_...), SendGrid keys, and other credentials hardcoded directly in React components.
// Actually found in a Lovable-generated file
const openai = new OpenAI({
apiKey: 'sk-proj-abc123...', // This is in your browser bundle
})
Anyone who opens DevTools, goes to the Sources tab, and searches for sk- or sk_live gets your keys. Attackers automate this. There are bots that specifically crawl JavaScript bundles looking for these patterns.
The financial impact is real. We had a client come to us after an exposed OpenAI key resulted in $4,200 in charges over a weekend. Stripe secret keys are worse -- they grant full access to process refunds, view customer data, and modify subscriptions.
The fix: Move all third-party API calls to server-side functions. Supabase Edge Functions work well for this:
// supabase/functions/openai-proxy/index.ts
import { serve } from 'https://deno.land/std@0.168.0/http/server.ts'
serve(async (req) => {
const { prompt } = await req.json()
const response = await fetch('https://api.openai.com/v1/chat/completions', {
method: 'POST',
headers: {
'Authorization': `Bearer ${Deno.env.get('OPENAI_API_KEY')}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
model: 'gpt-4o',
messages: [{ role: 'user', content: prompt }],
}),
})
return new Response(JSON.stringify(await response.json()))
})
Vulnerability 4: Missing Security Headers
The 200+ site scan found that most Lovable-deployed apps ship with zero security headers. No Content-Security-Policy. No Strict-Transport-Security. No X-Frame-Options. No X-Content-Type-Options.
This might seem minor compared to an exposed database, but missing headers enable:
- Clickjacking -- your app can be embedded in an iframe on a malicious site
- XSS amplification -- without CSP, injected scripts have no restrictions
- MIME type sniffing attacks -- browsers may interpret files as executable code
- Downgrade attacks -- without HSTS, traffic can be intercepted
| Header | Purpose | Lovable Default |
|---|---|---|
| Content-Security-Policy | Prevents XSS, controls resource loading | Missing |
| Strict-Transport-Security | Forces HTTPS | Missing |
| X-Frame-Options | Prevents clickjacking | Missing |
| X-Content-Type-Options | Prevents MIME sniffing | Missing |
| Referrer-Policy | Controls referrer information | Missing |
| Permissions-Policy | Controls browser features | Missing |
Vulnerability 5: No Input Validation or Sanitization
Lovable-generated forms typically send user input directly to Supabase without any validation. No length checks, no type validation, no sanitization of HTML or SQL-adjacent content.
While Supabase's PostgREST layer prevents traditional SQL injection, the lack of input validation still enables:
- Stored XSS through unsanitized HTML in text fields
- Denial of service through extremely large payloads
- Business logic abuse (e.g., negative quantities, prices of $0.00)
- Data corruption from unexpected types
What Lovable's Built-In Security Scan Actually Checks
Lovable does have a built-in "Security Scan" feature accessible from the dashboard. Credit where it's due -- it exists. But here's what it actually covers versus what it doesn't:
| Check | Built-in Scan | Production Audit |
|---|---|---|
| Basic syntax errors | ✅ | ✅ |
| Known dependency CVEs | Partial | ✅ |
| Hardcoded secrets in source | ❌ | ✅ |
| RLS enabled on all tables | ❌ | ✅ |
| RLS policy correctness | ❌ | ✅ |
| Service role key exposure | ❌ | ✅ |
| Security headers | ❌ | ✅ |
| Input validation coverage | ❌ | ✅ |
| Auth configuration review | ❌ | ✅ |
| Storage bucket policies | ❌ | ✅ |
| Rate limiting | ❌ | ✅ |
| Cookie security flags | ❌ | ✅ |
The built-in scan is surface-level at best. It won't catch the vulnerabilities that actually get exploited.
What a Production Audit Catches That the Platform Doesn't
When we do a production security audit for a client who's built on Lovable, here's what we typically find and fix. This is the real list, from actual engagements:
Database Layer
- Tables with RLS disabled (average: 60-70% of tables)
- RLS policies using
trueas the condition - Missing policies for DELETE operations (devs forget about delete)
- No policies on junction/join tables
- Storage buckets set to public with no upload restrictions
- Missing indexes on columns used in RLS policy conditions (performance + security)
Authentication Layer
- Weak JWT secrets (Supabase defaults are fine, but sometimes people change them)
- Missing email confirmation requirements
- No rate limiting on auth endpoints
- Password reset flows without proper token expiration
- OAuth redirect URL misconfigurations
Client Code Layer
service_rolekeys in frontend bundles- Third-party API keys hardcoded in components
.envfiles committed to git history- Debug logging that exposes user data in the console
- Error messages that leak database schema information
Infrastructure Layer
- No security headers whatsoever
- Cookies without
Secure,HttpOnly, orSameSiteflags - Exposed server version information
- No CORS configuration (accepts requests from any origin)
- Dependencies with known CVEs that haven't been updated in months
A typical Lovable app we audit needs 15-25 fixes before it's production-ready. Most of them take under an hour each, but you need to know they exist first.
The Moltbook Incident: A Real-World Case Study
In January 2026, security researchers at Wiz discovered that Moltbook -- an AI social network -- had its entire Supabase database exposed through a misconfigured client. The anon key was in the frontend JavaScript (normal), but RLS wasn't configured on critical tables (catastrophic).
The result? 1.5 million API keys were accessible. Not just user data -- actual API keys belonging to users who had connected their OpenAI, Anthropic, and other accounts. Full read and write access to every table. A researcher could browse the entire database just by using the Supabase client in a browser console.
The disclosure timeline was tight -- Moltbook's maintainer fixed the critical tables within hours of being contacted. But the damage window was unknowable. How long had the database been exposed before anyone checked? Nobody knows.
This is the Lovable + Supabase pattern playing out at scale. The platform generates working code. It just doesn't generate secure code.
How to Fix a Lovable App Before Going to Production
Here's the checklist we use. You can do most of this yourself if you're comfortable with SQL and Supabase's dashboard:
Step 1: Audit Every Table for RLS
-- Run this in Supabase SQL Editor to find tables without RLS
SELECT schemaname, tablename, rowsecurity
FROM pg_tables
WHERE schemaname = 'public';
Any table where rowsecurity is false needs immediate attention.
Step 2: Search Your Codebase for Secrets
# Search for common secret patterns
grep -rn 'sk-' --include='*.ts' --include='*.tsx' --include='*.js' .
grep -rn 'sk_live' --include='*.ts' --include='*.tsx' --include='*.js' .
grep -rn 'service_role' --include='*.ts' --include='*.tsx' --include='*.js' .
grep -rn 'SUPABASE_SERVICE' --include='*.ts' --include='*.tsx' --include='*.env' .
Step 3: Write Proper RLS Policies
For every table, write explicit policies for SELECT, INSERT, UPDATE, and DELETE. Always use auth.uid() checks:
-- Template for a user-owned table
ALTER TABLE your_table ENABLE ROW LEVEL SECURITY;
CREATE POLICY "select_own" ON your_table FOR SELECT
USING (auth.uid() = user_id);
CREATE POLICY "insert_own" ON your_table FOR INSERT
WITH CHECK (auth.uid() = user_id);
CREATE POLICY "update_own" ON your_table FOR UPDATE
USING (auth.uid() = user_id)
WITH CHECK (auth.uid() = user_id);
CREATE POLICY "delete_own" ON your_table FOR DELETE
USING (auth.uid() = user_id);
Step 4: Move API Calls Server-Side
Any third-party API call that requires a secret key needs to run in a Supabase Edge Function or a separate backend. This is non-negotiable.
Step 5: Add Security Headers
If you're deploying to Netlify, Vercel, or Cloudflare, add headers via their configuration. For Netlify, create a _headers file. For a Next.js app, add them in next.config.js.
Step 6: Consider a Framework Migration
For anything beyond an MVP, we often recommend migrating Lovable-generated React code into a proper Next.js or Astro project. This gives you server-side API routes, proper environment variable handling, middleware for auth checks, and a real build pipeline. It's more work upfront, but the security posture is night and day.
Tools for Automated Scanning
Several tools have emerged specifically for auditing AI-generated apps:
| Tool | What It Checks | Cost |
|---|---|---|
Ship Safe (npx ship-safe audit .) |
RLS, service_role exposure, storage buckets, dependency CVEs | Free, open-source |
| Vibe App Scanner (vibeappscanner.com) | Full security scan for AI-built apps | Free starter scan |
| Snyk | Dependency vulnerabilities, code scanning | Free tier available |
| Supabase Dashboard → Auth → Policies | Visual RLS policy editor | Included with Supabase |
Ship Safe is the one I'd start with. It runs locally, nothing leaves your machine, and it's specifically built for the Supabase misconfigurations that AI tools create:
npx ship-safe audit .
It'll flag disabled RLS, service_role keys in client code, open storage buckets, weak auth config, hardcoded secrets, and dependency CVEs.
FAQ
Is the Supabase anon key safe to expose in frontend code?
Yes -- but only if you have proper RLS policies on every table. The anon key is designed to be public. It's like a project identifier. The security comes from RLS policies that control what that key can actually access. Without RLS, the anon key gives anyone full database access.
Does Lovable enable RLS by default when creating tables?
No. As of early 2026, Lovable creates Supabase tables without enabling RLS by default. This is the single biggest security gap in the platform. You need to manually enable RLS and write policies for every table after Lovable generates them. CVE-2025-48757 was a direct result of this default behavior.
How do I check if my Lovable app has exposed secrets?
Open your deployed app in a browser, open DevTools (F12), go to the Sources tab, and search across all files for sk-, sk_live, service_role, and any API key prefixes for services you use. Also run npx ship-safe audit . locally on your codebase for automated detection.
Can Lovable's built-in security scan catch RLS issues?
The built-in security scan doesn't check for RLS misconfigurations, missing policies, or exposed service keys. It covers basic code-level issues but misses the database and infrastructure vulnerabilities that represent the highest risk. You need external tooling for a real security assessment.
What happened with CVE-2025-48757?
CVE-2025-48757 was a vulnerability disclosure that identified 303 vulnerable API endpoints across 170+ apps built with Lovable. The root cause was Lovable creating Supabase tables without enabling RLS, leaving entire databases accessible to anyone with the publicly available anon key. It highlighted the systemic nature of the problem.
Should I migrate away from Lovable for production apps?
Not necessarily. Lovable is excellent for rapid prototyping and building MVPs. But the generated code needs significant security hardening before production use. Many teams use Lovable to build the initial version, then migrate to a proper framework with server-side rendering, proper secret management, and security middleware. That's a reasonable approach.
How long does it take to secure a Lovable app for production?
For a typical app with 10-20 tables, expect 2-5 days of focused work to audit all RLS policies, move secrets server-side, add security headers, validate inputs, and test everything. More complex apps with storage buckets, real-time subscriptions, and multiple user roles can take longer. It's not insurmountable, but it's not a one-hour task either.
Are other AI app builders like Bolt or Cursor safer than Lovable?
The 200+ site scan found that security vulnerabilities were concentrated in Lovable + Supabase applications specifically. Bolt, Replit, and Cursor/Cline-based apps didn't show the same pattern of RLS misconfigurations. That doesn't mean they're perfectly secure -- all AI-generated code needs review -- but the Lovable-specific Supabase integration creates a unique class of database exposure vulnerabilities that other tools don't have.