• Agents
  • Docs
  • Pricing
  • Blog
Log in
Get started

Security for apps built with AI. Paste a URL, get a report, fix what matters.

Product

  • How it works
  • What we find
  • Pricing
  • Agents
  • MCP Server
  • CLI
  • GitHub Action

Resources

  • Blog
  • Docs
  • FAQ
  • Glossary

Security

  • Supabase Security
  • Next.js Security
  • Lovable Security
  • Cursor Security
  • Bolt Security

Legal

  • Privacy Policy
  • Terms of Service
  • Cookie Policy
  • Imprint
© 2026 Flowpatrol. All rights reserved.
Back to Blog
Guides

How to Secure Your Lovable App Before You Launch

A step-by-step security guide for apps built with Lovable. Fix the most common vulnerabilities in under an hour — no security expertise required.

Flowpatrol TeamMar 28, 202610 min read
How to Secure Your Lovable App Before You Launch

How do you secure a Lovable app before launch?

To secure your Lovable app, you need to do seven things: enable Row Level Security on every Supabase table, audit your environment variables for leaked secrets, verify authentication is enforced server-side, test for IDOR across user-specific endpoints, add security headers, review file upload handling, and set up monitoring. The whole process takes about an hour. No security background needed.

This matters because Lovable's AI has a documented pattern of shipping apps without proper security configuration. In May 2025, CVE-2025-48757 revealed that 170+ Lovable-built apps had missing Row Level Security, exposing 303 vulnerable endpoints — including personal debt records, home addresses, and API keys. The issue isn't Supabase. It's that Lovable's AI generates database tables without enabling the security features that make Supabase safe for client-side access.

The good news: every issue has a concrete fix. Here's the step-by-step guide.


Why do Lovable apps need a security review?

Every Lovable app is built on the same stack: React frontend + Supabase backend. This is a good stack. But Lovable's AI consistently generates apps without proper security configuration — RLS disabled, secrets in client bundles, auth checks missing on API routes.

Our scan data backs this up: Lovable apps had the highest vulnerability rate of any platform we tested, with 47% containing critical vulnerabilities and 88% containing high-severity issues. The average Lovable app had 5.2 findings. The combination of always-exposed Supabase credentials and systematically missing RLS creates a pattern that affects almost every app on the platform.


Step 1: How do you enable Row Level Security on every table?

Time: 10 minutes | Impact: Critical

This is the single most important step. For a deep dive on how RLS works and why AI skips it, see our full RLS guide. Open your Supabase dashboard, go to the SQL Editor, and run this to see where you stand:

SELECT tablename, rowsecurity
FROM pg_tables
WHERE schemaname = 'public'
ORDER BY tablename;

For every table that shows false, you need to enable RLS and create access policies.

Security guide progress checklist showing step one complete

Enable RLS

-- Replace with your actual table names
ALTER TABLE profiles ENABLE ROW LEVEL SECURITY;
ALTER TABLE items ENABLE ROW LEVEL SECURITY;
ALTER TABLE orders ENABLE ROW LEVEL SECURITY;
ALTER TABLE messages ENABLE ROW LEVEL SECURITY;
-- Repeat for EVERY table

Create basic policies

For most tables in a Lovable app, you want "users can only access their own data." The user ID column is typically user_id or created_by:

-- Profiles: users read and update their own profile
CREATE POLICY "Users manage own profile"
ON profiles FOR ALL
USING (auth.uid() = id);

-- User-owned data: full CRUD on own rows
CREATE POLICY "Users manage own items"
ON items FOR ALL
USING (auth.uid() = user_id);

-- For INSERT, also restrict which user_id can be set
CREATE POLICY "Users create own items"
ON items FOR INSERT
WITH CHECK (auth.uid() = user_id);

If your app has shared or public data (like published listings), add a separate read policy:

CREATE POLICY "Anyone can view published listings"
ON listings FOR SELECT
USING (status = 'published');

Verify it worked

Open an incognito browser window, go to your app, and check that unauthenticated users can't see data they shouldn't. You can also test directly:

curl "https://YOUR-PROJECT.supabase.co/rest/v1/profiles?select=*" \
  -H "apikey: YOUR_ANON_KEY" \
  -H "Authorization: Bearer YOUR_ANON_KEY"

This should return an empty array or an error — not your users' data.


Step 2: How do you find leaked secrets in your Lovable app?

Time: 10 minutes | Impact: Critical

Lovable apps deploy to their own hosting. Your environment variables might be leaking into the browser. For the full breakdown of what leaks and why, see Your .env Is Showing.

Check what's in your bundle

  1. Open your deployed app in Chrome
  2. Open DevTools (F12) → Sources tab
  3. Search across all files (Ctrl+Shift+F) for these patterns:
    • sk- (OpenAI keys)
    • sk_live (Stripe secret keys)
    • service_role (Supabase service role key)
    • SUPABASE_SERVICE or SERVICE_ROLE
    • secret or SECRET

Safe to find in client code:

  • Supabase anon key (starts with eyJ...) — safe IF RLS is enabled
  • Supabase project URL
  • Stripe publishable key (pk_live_...)

Must NOT be in client code:

  • OpenAI/Anthropic API keys
  • Stripe secret key
  • Supabase service role key
  • Any password or secret token

If you find exposed secrets

  1. Rotate them immediately. Generate new keys from the provider's dashboard. The old ones are compromised.
  2. Move them server-side. Use Supabase Edge Functions or Next.js API routes to keep secrets on the server.

Example — moving an OpenAI call server-side with a Supabase Edge Function:

// supabase/functions/ai-chat/index.ts
import { serve } from "https://deno.land/std/http/server.ts";

serve(async (req) => {
  const { message } = 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-4",
        messages: [{ role: "user", content: message }],
      }),
    }
  );

  const data = await response.json();
  return new Response(JSON.stringify(data));
});

Step 3: How do you verify authentication is enforced?

Time: 15 minutes | Impact: High

Lovable generates auth flows (login, signup, protected routes) but doesn't always enforce them consistently.

Test your protected pages

  1. Log out of your app
  2. Try to access protected URLs directly (e.g., /dashboard, /settings, /api/user)
  3. Each one should redirect to login — not show the page content

Test your API endpoints

If your app has API routes, test them without authentication:

# Try accessing an API endpoint with no auth token
curl "https://your-app.lovable.app/api/data"
# Should return 401 Unauthorized, not data

# Try with just the anon key (no user session)
curl "https://YOUR-PROJECT.supabase.co/rest/v1/user_data?select=*" \
  -H "apikey: YOUR_ANON_KEY"
# Should return empty (if RLS is working)

Common Lovable auth gaps

  • Client-side only checks: The UI redirects to login, but the API endpoint returns data without auth
  • Missing middleware: Some routes are protected, others aren't
  • Supabase Auth not verified server-side: The app reads from supabase.auth.getUser() on the client but doesn't verify the JWT on server-side routes

Step 4: How do you check for IDOR vulnerabilities?

Time: 10 minutes | Impact: High

If your app has user-specific data, test whether users can access each other's resources.

How to test

  1. Create two test accounts (User A and User B)
  2. Log in as User A, create some data, and note the resource IDs from the URL or API responses
  3. Log in as User B
  4. Try to access User A's resources by manually entering their IDs
# As User B, try to access User A's invoice
GET /api/invoices/USER_A_INVOICE_ID

# This should return 404 or 403, not the invoice

If User B can see User A's data, you have an IDOR vulnerability. Fix it by adding ownership checks to every endpoint that serves user-specific data:

// In your API route or server action
const invoice = await supabase
  .from("invoices")
  .select("*")
  .eq("id", invoiceId)
  .eq("user_id", user.id) // Ownership check
  .single();

If you've set up RLS properly in Step 1, this should already be enforced at the database level. But it's good practice to check at the API level too — defense in depth.


Step 5: How do you add security headers?

Time: 5 minutes | Impact: Medium

Security headers tell browsers how to handle your content safely. Lovable apps usually don't include them.

If your Lovable app uses Vite (most do), you can add headers through your deployment platform. For Lovable's built-in hosting, check if you can configure custom headers. For Vercel or Netlify, use their configuration files.

For Vercel deployment (vercel.json)

{
  "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"
        },
        {
          "key": "Permissions-Policy",
          "value": "camera=(), microphone=(), geolocation=()"
        }
      ]
    }
  ]
}

For Netlify (_headers file)

/*
  X-Frame-Options: DENY
  X-Content-Type-Options: nosniff
  Referrer-Policy: strict-origin-when-cross-origin
  Strict-Transport-Security: max-age=31536000; includeSubDomains
  Permissions-Policy: camera=(), microphone=(), geolocation=()

Step 6: How do you secure file uploads?

Time: 5 minutes (if applicable) | Impact: Medium

If your Lovable app lets users upload files (images, documents, etc.), check that:

  1. File types are validated. Only accept the types you expect (e.g., images only: JPEG, PNG, WebP).
  2. File sizes are limited. Set a reasonable max (5MB for images, 10MB for documents).
  3. Files go to Supabase Storage, not your app server. Supabase Storage handles files safely in a separate domain.
  4. Storage bucket policies are set. In your Supabase dashboard, check that storage buckets have appropriate access policies.
-- Example: only the file owner can access their uploads
CREATE POLICY "Users access own uploads"
ON storage.objects FOR ALL
USING (auth.uid()::text = (storage.foldername(name))[1]);

Step 7: How do you set up security monitoring?

Time: 5 minutes | Impact: Medium

Even after fixing everything, you want to know if something goes wrong.

Enable Supabase logs

In your Supabase dashboard:

  1. Go to Settings > API and ensure request logging is enabled
  2. Go to Database > Logs and check for unusual query patterns
  3. Set up email alerts for failed authentication attempts

Monitor for key abuse

If you're using third-party APIs (OpenAI, Stripe), set up:

  • Usage alerts on your OpenAI dashboard (alert at $50, $100, etc.)
  • Stripe webhook monitoring for unexpected activity
  • Supabase Auth email notifications for new signups (spot if someone is creating bulk accounts)

What's the complete Lovable security checklist?

Here's everything in one list. Work through it top to bottom:

  • RLS enabled on every Supabase table
  • RLS policies created for every table
  • No secrets in client-side JavaScript (except anon key and publishable keys)
  • All exposed secrets rotated
  • Protected pages redirect to login when unauthenticated
  • API endpoints return 401 without valid auth
  • Users cannot access other users' data (no IDOR)
  • Security headers configured on deployment
  • File uploads validated for type and size (if applicable)
  • Supabase Storage policies configured (if applicable)
  • Usage alerts set on third-party APIs
  • Supabase auth logs reviewed

What comes after the manual review?

You've done the manual review. Your app is significantly more secure than most vibe-coded apps we've scanned. But security isn't a one-time thing — it matters every time you add a feature, create a new table, or integrate a new service.

That's where automated scanning comes in. Flowpatrol runs the same checks you just did (and 50+ more) automatically, every time you want. Paste your URL, get a report in five minutes, fix what matters.

Sign up for Flowpatrol and make security part of your build process — not an afterthought.


This guide is current as of February 2026. Lovable's platform may add additional security features over time — check their documentation for the latest. The Supabase-specific steps apply to any app using Supabase, regardless of which tool built it.

Back to all posts