Lovable is impressive. In an afternoon, you can go from an idea to a working web app with authentication, a database, and a payment flow. But most Lovable apps ship with the same five or six security vulnerabilities — not because Lovable is insecure, but because security configuration requires deliberate choices that the AI doesn't make for you.
This guide covers the vulnerabilities that show up most often in Lovable apps, why they happen, and exactly how to fix them.
The Supabase ANON key is public — and that's not the problem you think it is
Every Lovable app that uses Supabase ships with a Supabase ANON key in the frontend JavaScript. This is expected and fine — the ANON key is designed to be public. The problem is what the ANON key can access.
By default, Supabase tables have Row Level Security (RLS) disabled. With RLS off and an ANON key in the browser, anyone with DevTools can query your entire database directly from the browser console:
const { data } = await supabase.from('users').select('*')
That call works — and returns every user in your database — unless you have RLS policies in place.
How to fix it: Go to your Supabase project → Authentication → Policies → and enable RLS on every table. Then add policies for each table that define who can read and write what. The simplest policy for user data:
-- Users can only read their own row
CREATE POLICY "Users can read own data"
ON users FOR SELECT
USING (auth.uid() = user_id);
Run VibeScan to verify your Supabase ANON key is not paired with tables that have RLS disabled.
API routes generated by Lovable often have no authentication check
Lovable generates working features fast. When it creates a new API route, it focuses on making the feature work — not on securing it. The result is API routes that return or modify user data without checking who is making the request.
A typical unprotected Lovable route:
// api/profile/route.ts
export async function GET(req: Request) {
const { data } = await supabase.from('profiles').select('*')
return Response.json(data)
}
This returns all profiles to anyone who calls the URL. No authentication required.
How to fix it: Every API route that touches user data needs an auth check at the top. In Next.js with Supabase:
export async function GET(req: Request) {
const supabase = createRouteHandlerClient({ cookies })
const { data: { session } } = await supabase.auth.getSession()
if (!session) return Response.json({ error: 'Unauthorized' }, { status: 401 })
const { data } = await supabase
.from('profiles')
.select('*')
.eq('user_id', session.user.id) // filter by authenticated user
return Response.json(data)
}
After Lovable generates any new feature, review every new API file it created and add this pattern.
CORS is set to wildcard in most Lovable deployments
Lovable apps often deploy with Access-Control-Allow-Origin: * — the widest possible CORS policy. This setting means any website can make cross-origin requests to your API using your users' credentials.
In practice, this means an attacker can build a page that quietly calls your API when a logged-in user visits it. If your API routes aren't checking authentication (see above), this compounds the problem significantly.
How to fix it: In your API routes or middleware, set CORS to your specific domain:
const headers = {
'Access-Control-Allow-Origin': 'https://your-app.lovable.app',
'Access-Control-Allow-Methods': 'GET, POST, PUT, DELETE',
'Access-Control-Allow-Headers': 'Content-Type, Authorization',
}
In Supabase, go to Project Settings → API → and add your specific domain to the allowed origins list.
Secrets stored in localStorage can be read by any JavaScript on the page
Lovable sometimes stores sensitive values — auth tokens, user state, session data — in localStorage for persistence between page loads. Any JavaScript running on your page can read localStorage, including scripts from third-party packages you've installed.
If your app uses any analytics, chat widgets, or marketing tools, those scripts have access to everything in localStorage.
How to fix it: Supabase's built-in auth handles session storage correctly by default — don't override it. For other sensitive values, use httpOnly cookies instead of localStorage. httpOnly cookies cannot be read by JavaScript at all.
For any Lovable app using Supabase auth, verify you haven't added any localStorage calls that store auth tokens or API keys.
Missing security headers leave the door open for XSS and clickjacking
Lovable apps deployed to Vercel don't get security headers automatically. Without them:
- No Content-Security-Policy — an XSS vulnerability lets an attacker run any script
- No X-Frame-Options — your app can be embedded in an iframe to steal clicks
- No HSTS — browsers won't automatically upgrade HTTP to HTTPS
How to fix it: Add a vercel.json file to your project root:
{
"headers": [
{
"source": "/(.*)",
"headers": [
{ "key": "X-Frame-Options", "value": "DENY" },
{ "key": "X-Content-Type-Options", "value": "nosniff" },
{ "key": "Referrer-Policy", "value": "strict-origin-when-cross-origin" },
{ "key": "Strict-Transport-Security", "value": "max-age=31536000; includeSubDomains" }
]
}
]
}
This file gets picked up automatically on your next Vercel deployment. VibeScan checks for all of these headers — run a scan after deploying to verify they're live.
A security checklist for every new Lovable feature
After Lovable generates any new feature, go through this list before you deploy:
- Every new API route has an auth check at the top
- No new tables were created with RLS disabled
- No secrets or tokens are stored in localStorage
- Any new third-party API keys are in environment variables, not in the code
- CORS is locked to your domain, not wildcard
Run VibeScan after each major deployment to catch anything that slipped through. The scan takes under 60 seconds and checks the things that are hardest to verify manually.
The bigger picture
Lovable's security gaps aren't bugs — they're the natural result of AI code generation prioritizing working software over security configuration. The AI doesn't know which routes need authentication or which tables contain sensitive data. That context lives in your head, not the model.
The good news: these gaps are all fixable in an afternoon. Enable RLS, add auth checks to API routes, set security headers, and lock down CORS. Those four changes fix the majority of vulnerabilities in most Lovable apps.