← All posts
May 1, 2026lovablesupabaserlssecurity

The most common security mistakes in Lovable apps

CVE-2025-48757 exposed 170+ Lovable apps. Here are the three security patterns that keep causing breaches — and how to fix each one before you launch.

In April 2026, Lovable disclosed CVE-2025-48757 — a backend regression that re-enabled public access to user projects, source code, and database credentials. Any free account could read other users' data. Over 170 apps were potentially exposed before the issue was patched.

This was not a theoretical vulnerability. It was a production incident affecting real users and real data.

What made it possible was not one unusual mistake. It was three patterns that appear in the majority of AI-built Lovable apps. The same patterns show up consistently in every independent audit of this category.


Pattern 1: Supabase RLS policies that say USING (true)

Row Level Security is the mechanism that prevents user A from reading user B's data. When you enable RLS in Supabase, you have to write a policy that defines who can access which rows.

The problem is what AI tools write by default:

CREATE POLICY "Users can read their data"
  ON public.profiles
  FOR SELECT
  USING (true);

USING (true) means every row is accessible to every request. The policy name says "users can read their data" but the logic says "anyone can read everything." The RLS is enabled — the Supabase dashboard shows a green checkmark — but the data is completely open.

The correct policy for user-scoped data:

CREATE POLICY "Users can read their own data"
  ON public.profiles
  FOR SELECT
  USING (auth.uid() = user_id);

This grants access only when the authenticated user's ID matches the user_id column on the row. Anyone without a matching session gets nothing.

How to check: Go to Supabase Dashboard → Table Editor → your table → RLS policies. Read every USING clause. If it says true, your data is open.


Pattern 2: API keys in client-side JavaScript

AI tools generate working code. The fastest path to a working Supabase client in a React component is to reference the environment variable directly. The problem is which environment variables are available client-side.

In Next.js, any variable prefixed with NEXT_PUBLIC_ is embedded in the browser bundle. That is by design — it is how you share config with the client. But it means anything you put in a NEXT_PUBLIC_ variable is readable by anyone who visits your app and opens DevTools.

The Supabase anon key is safe to expose — it is designed to be public and is rate-limited by Supabase. Your service_role key is not. Your Stripe secret key is not. Your OpenAI key is not.

The Moltbook breach involved plaintext OpenAI keys in the deployed bundle. The Enrichlead breach involved Stripe credentials in client code. Both were Lovable-built apps. Both were exploited within days of launch.

How to check: Open your deployed app in a browser. Open DevTools → Sources → search for your key prefixes (sk_, openai, stripe, database hostnames). If they appear, they are in your bundle.

Fix: Server-side API calls only for anything that requires a secret key. In Next.js, this means Route Handlers (app/api/) or Server Actions — never client components.


Pattern 3: No security headers

HTTP security headers tell browsers how to behave with your content. They prevent clickjacking, script injection, MIME sniffing, and cross-origin data leaks. They require explicit configuration — AI tools do not set them by default.

The most important ones for a Lovable/Vercel app:

// next.config.js
async headers() {
  return [{
    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" },
      {
        key: "Content-Security-Policy",
        value: "default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'; img-src 'self' data: blob:; connect-src 'self' https://your-project.supabase.co"
      },
    ],
  }];
}

VibeWrench found that 86%+ of 100 scanned AI-built apps had no meaningful security headers. This is not a subtle misconfiguration — it is a missing baseline that is straightforward to add.


Before you launch

These three patterns — open RLS, exposed secrets, missing headers — are the most common critical findings in every independent audit of AI-built apps. They are also all checkable in under 30 seconds.

Run VibeScan on your deployed app → It checks your live surface for exposed endpoints, header configuration, and Supabase public surface issues. Free scan, no GitHub access needed.


Sources: CVE-2025-48757 (Lovable, April 2026); Moltbook incident report; PreBreach OWASP Top 10 in AI-Generated Code (Feb 2026); VibeWrench 100-app benchmark.

Check your own app

Free scan — no GitHub access needed. Takes 30 seconds.

Scan my app free