Lovable + Supabase security playbook (post April 2026 BOLA breach)

Updated

Lovable hit $6.6B and $100M ARR — and the April 2026 BOLA disclosure. The structural fix: every Lovable app needs (1) RLS on every Supabase table, (2) tenant-scoped policies, (3) no direct browser-to-anon-key REST calls without RLS protection. See /incidents/lovable-bola-april-2026 for the full case.

What breaks on this stack

RLS disabled on at least one Supabase table

10.3% of Lovable apps had this in April 2026. Enable RLS on every table; default-deny baseline.

Read the guide →

Hardcoded anon_key in client bundle

Lovable's generator hardcodes the anon_key. anon_key is public BY DESIGN — without RLS, it's a skeleton key.

Read the guide →

Cross-tenant data leak via shared user_id

Policies scoping by auth.uid() only fail when user_ids span tenants. Add tenant claim from JWT.

Read the guide →

Storage buckets default-public

Supabase Storage buckets need RLS too; many Lovable templates leave them public.

Read the guide →

Pre-ship checklist

  • RLS enabled on every table (alter table T enable row level security)
  • Default-deny policy layered under explicit allows
  • Tenant-scoped (auth.uid() AND tenant claim from JWT)
  • anon_key only used with RLS-protected tables
  • Storage buckets have RLS policies
  • Service role key server-only

Starter config

-- canonical Supabase RLS bundle for Lovable apps
alter table public.orders enable row level security;
create policy "users_read_own_in_tenant" on public.orders for select
  using (auth.uid() = user_id and tenant_id = (auth.jwt() ->> 'tenant')::uuid);