Vibe coding lets you describe an app in plain English and get a working product back in minutes. Lovable, one of the biggest platforms doing this, has an AI agent build the frontend, the login flow and the database connection from a single prompt. Anton Osika and Fabian Hedin founded it in Stockholm in 2023. It grew out of Osika’s open-source project GPT Engineer, spent a short time as the GPT Engineer App, and launched publicly as Lovable in November 2024. The company says it has hosted more than fifty million projects and adds about 1.2 million new builds every week.
The tool removes syntax errors, dependency management, migration files and API plumbing, so non-technical founders, product managers and domain experts can ship production web apps without writing code. A large-scale Lovable security investigation by the research group Crissy Field and the German business daily Handelsblatt shows what that convenience hides. Journalist Lina Knees first reported it on November 2, 2026, and an updated technical report followed. The researchers examined 159,041 publicly deployed Lovable apps crawled between December 2025 and September 2026 and found thousands where sensitive personal, commercial and identity data could be pulled by anyone on the internet without logging in.
No zero-day in the database software is involved, and the report does not claim that every AI-built app is broken. The problem comes from three things meeting: how AI agents generate code, permissive defaults when a database is provisioned programmatically, and marketing that tells users no technical knowledge is required. Lovable’s marketing stresses effortless creation, yet its Terms and Conditions put full legal and operational responsibility for application security and data handling on the customer. Between what non-technical builders assume the platform handles and what the cloud infrastructure enforces by default, hundreds of thousands of private user records ended up readable by unauthenticated queries.

How Supabase, PostgREST and Row Level Security create the gap
Why did thousands of unrelated apps share the same vulnerability? The answer sits in the architecture between a Lovable frontend and its database. Lovable added its own native database features in late 2025, but they were less widely used during the study window. Most data-driven Lovable projects run on Supabase, an open-source, hosted backend-as-a-service built on PostgreSQL. Of the 159,041 projects the researchers analyzed, 34,545 used Supabase as their main database.
How Supabase talks to the browser without a backend server
In a traditional three-tier web architecture, the browser never talks to the database. Requests go to an application server written in Node.js, Python, Go or Rust. That server validates the user’s session, runs business logic, checks permissions, and queries the database over a private network with high-privilege credentials kept in server environment variables.
Supabase drops that middle layer for standard CRUD (create, read, update, delete) operations by putting PostgREST directly in front of PostgreSQL. PostgREST is a standalone web server that turns a PostgreSQL schema into a RESTful HTTP API.

Why the Supabase anon key is public by design
A Lovable app is usually compiled into a client-side single-page application that runs in the visitor’s browser, so it has to hold credentials for the Supabase Data API. Every Supabase-connected Lovable build therefore ships two values inside its compiled JavaScript bundle: the Supabase project URL (https://<project_ref>.supabase.co) and a public API token. Current documentation calls the token the publishable key. Older codebases call it the anon key.
Putting the anon key in client-side code is intended. The token is a signed JSON Web Token (JWT) whose payload names the PostgreSQL role to use:
{ "role": "anon", "iss": "supabase", "iat": 1735689600, "exp": 1893456000}
When a client sends this token in the apikey and Authorization: Bearer headers, PostgREST verifies the signature and tells PostgreSQL to run the transaction as the anon role (SET LOCAL role = 'anon';). A user who logs in through Supabase Auth gets a different JWT, with the role claim set to authenticated and a sub claim holding the user’s UUID (auth.uid()).
Because the browser can query the API directly, access control cannot live in frontend JavaScript. Any visitor can open developer tools, copy the anon key, and send arbitrary requests with curl or a Python script. Supabase hands every authorization decision to PostgreSQL’s Row Level Security (RLS) engine. With RLS enabled on a table, PostgreSQL denies by default. Even if a role has table-level SELECT, INSERT, UPDATE or DELETE privileges, no rows are visible or changeable unless at least one CREATE POLICY rule evaluates to true for that row.
📬 Stay Ahead of Cyber Threats
Get the latest cybersecurity news, critical vulnerabilities, threat intelligence, tutorials, and exclusive giveaways delivered straight to your inbox. No spam. Unsubscribe anytime.
Subscribe to the Newsletter →Default privileges versus default RLS
The failure comes from a mismatch between how Supabase sets table permissions and how it sets RLS.
A standard Supabase PostgreSQL instance grants broad default privileges on the public schema (GRANT ALL ON ALL TABLES IN SCHEMA public TO anon, authenticated;). That lets the PostgREST API use a new table immediately, with no manual GRANT statements.
When a developer creates a table in the Supabase dashboard’s Table Editor, the interface ticks the “Enable Row Level Security (RLS)” box by default. PostgreSQL itself does not enable RLS on new tables. A table created through raw SQL (CREATE TABLE public.customers (...);), a database migration or an API call has RLS off unless the creator runs ALTER TABLE public.customers ENABLE ROW LEVEL SECURITY;.
Why AI coding agents leave RLS off
An AI coding agent does not click through the Supabase dashboard. When a user asks Lovable for an invoicing portal, a property management dashboard or a community forum, the agent writes raw SQL migrations and runs them against the connected database. Its main goal is to confirm that data from a submitted form is written and shown back on screen. Skipping RLS, or writing an overly permissive policy (USING (true)), is the easiest way to get there. If the agent enables RLS without writing correct policies that match the frontend’s authentication state, the app breaks in testing and returns empty arrays or HTTP 401 and 403 errors.
With RLS off on a public table, the default anon grants plus PostgREST turn the public publishable key into a master key. Supabase’s own documentation says so plainly: “Without RLS, anyone with your anon key can access all data.” The same pattern across Lovable builds was cataloged in 2025 as CVE-2025-48757, which documented AI-generated schemas deploying public API keys that point at tables with no row-level protection.
Vulnerable table versus secured table
-- 1. What the AI agent generates by default to make the app work immediately:CREATE TABLE public.passport_submissions ( id uuid PRIMARY KEY DEFAULT gen_random_uuid(), user_id uuid REFERENCES auth.users(id), full_name text NOT NULL, passport_number text NOT NULL, nationality text NOT NULL, expiration_date date NOT NULL, created_at timestamptz DEFAULT now());-- State: RLS is DISABLED. Because 'anon' has default SELECT privileges on 'public',-- an unauthenticated GET /rest/v1/passport_submissions?select=* dumps the entire table.-- 2. What is required to actually secure the table against unauthenticated extraction:ALTER TABLE public.passport_submissions ENABLE ROW LEVEL SECURITY;CREATE POLICY "Users can only read their own passport records"ON public.passport_submissionsFOR SELECTTO authenticatedUSING ((SELECT auth.uid()) = user_id);-- State: RLS is ENABLED. Role 'anon' has no matching policy and receives 0 rows ([]).-- Role 'authenticated' only receives rows where user_id matches their signed JWT 'sub' claim.
How Crissy Field measured the exposure
To find out how often this vulnerability shows up in live apps, the Crissy Field team used two phases: passive archive analysis, then targeted read-only API checks.
finding Lovable apps in Common Crawl
The researchers skipped intrusive port scanning and brute-force subdomain enumeration. They started from Common Crawl, the open web archive that publishes petabyte-scale datasets in Apache Parquet and WARC formats on Amazon S3. They queried archives from December 2025 to September 2026, using tools such as DuckDB to filter HTML metadata, JavaScript bundle patterns and platform fingerprints, and identified 159,041 distinct Lovable projects.
Static analysis of client-side assets and network initialization showed that 34,545 of those projects used Supabase as their backend. The researchers then loaded the apps in a browser without logging in or interacting. 24,664 sites fetched and received database records from Supabase on page load.
Receiving records on page load does not prove a vulnerability on its own. Many legitimate apps query a database at startup to fill public elements, such as an online store loading its product catalog, a conference site listing its speaker schedule, or a directory showing public business listings.
read-only API checks and schema enumeration
To separate public display from accidental exposure, the second phase tested whether the anon key a site already sent on page load could read sensitive tables beyond what the interface showed.
In a standard Supabase deployment with PostgREST exposed, an unauthenticated GET request to the REST root (https://<project_ref>.supabase.co/rest/v1/) with the anon key returns an OpenAPI (Swagger) specification. It describes every table, view, column name, data type and stored procedure (rpc) in the public schema. Even without it, table names often appear in the minified client-side bundle (supabase.from('users').select('*')).
Using the publishable key the sites had already transmitted, the researchers made further strictly read-only requests to inspect the contents of accessible tables across the 24,664 sites. To flag possible personally identifiable information (PII) at scale without reading millions of rows by hand, they scanned the returned payloads for email addresses.
The sample narrowed like this:
- 159,041 Lovable projects identified through Common Crawl (December 2025 to September 2026)
- 34,545 projects confirmed to use Supabase for their database
- 24,664 sites that returned Supabase records on page load with no authentication
- 7,403 sites, 30% of those 24,664, that exposed records containing email addresses across 10,560 distinct tables, readable with read-only requests using the site’s own publishable key
Limits of the 30% figure
The Crissy Field report warns against reading 30% as a confirmed leak rate across all Lovable apps. It names several caveats.
Email addresses are a rough proxy for personal data. A table might hold a company’s public info@ support address, or synthetic data such as [email protected] that the AI generated while prototyping. Searching only for emails also misses sensitive tables indexed by a UUID or phone number, such as medical notes, internal financial ledgers, chat logs, or identity document tables linked through foreign keys. These two errors partly cancel out, and the researchers could not measure the net effect.
The 159,041 sites also came from Common Crawl, which captures sites that are linked on the public web and indexable by crawlers. It is not a uniform random sample of Lovable’s fifty million projects, many of which are abandoned single-prompt experiments or private unindexed links.
Finally, for ethical reasons and to minimize data collection, the researchers retrieved only partial slices of exposed tables instead of full dumps. They did not publish victim URLs or reproduction scripts. The record counts are therefore a conservative floor, and the real number of exposed records is almost certainly higher.
What data was exposed in Lovable apps
The partial datasets held far more than forgotten test strings or newsletter signups. Production apps handling sensitive work across consumer communities, local commerce, real estate and identity verification were running with wide-open tables. The worst cases fell into five groups.
Government identity documents
One service provider exposed more than 1,000 records with passport numbers, passport expiration dates and nationalities. A leaked password or card number can be rotated or canceled. Identity document data cannot. Combined with full names and nationalities, it gives attackers what they need for synthetic identity fraud, unauthorized financial onboarding and travel impersonation.
Private chats and user profiles on a community platform
A German lifestyle forum exposed more than 80,000 user profiles containing full legal names, email addresses, dates of birth and gender. More than 200,000 private chat messages were also readable without authentication. For members of a lifestyle community, being able to match pseudonymous chat histories to real names and birthdates is a serious privacy violation.
Ticketing, restaurant and payment records
Several event organizers and restaurants exposed tens of thousands of transaction records for ticket bookings and food orders. Anyone querying the backend without logging in could get customer email addresses, phone numbers, postal addresses, payment information and valid ticket codes. Live ticket codes allow immediate fraud and disruption at venues. Order histories paired with home addresses give attackers convincing pretexts for targeted smishing and phishing.
Internal business data and AI-generated email summaries
A property management company left a table of AI-generated summaries of internal corporate emails unprotected. The summaries covered sensitive communications about residential tenants, property owners and commercial business partners. Elsewhere in the dataset, researchers found tens of thousands of business contracts, financial invoices, personal photo albums and logs of internal WhatsApp communications.
Customer support and CRM tables
Researchers also found widespread exposure of customer relationship management (CRM) tables: private waiting lists, support inquiries, contact form submissions and newsletter subscriber databases. In one case, 280,000 emails sent to a provider’s customers could be read with unauthenticated queries.
Why AI app builders make the problem worse
Access control mistakes are as old as relational databases. Human developers have left Amazon S3 buckets, Elasticsearch clusters and MongoDB instances open to the public for more than a decade. The Crissy Field and Handelsblatt investigation finds that AI app builders repeat those mistakes at scale and make them uniform.
Nothing in the preview shows the database is open
Traditional development has built-in friction. A developer designs the relational schema, configures an object-relational mapper or query builder, sets up authentication middleware, and works out how state moves between client and server. That friction forces reflection, and an engineer writing a SQL migration by hand is already thinking like a database administrator.
AI app builders strip that context away. The user sees a chat box and a live preview of the frontend. Suppose they ask the AI to “Add a page where customers can upload their passport details for verification.” They judge success by looking: does the form look professional, does a success toast appear after Submit, does the admin view show the new row? A database secured with authenticated JWTs and strict auth.uid() RLS policies looks identical in that preview to an unauthenticated database with RLS disabled. A builder without a technical background gets no visual sign that the data is open to the entire internet.
Uniform AI-generated code makes attacks easy to script
Human developers structure APIs in many different ways, with different endpoint names and custom backend routes wrapped around database calls. Lovable’s AI agent works from standardized system instructions and produces highly uniform directory structures, predictable table names (profiles, messages, orders, invoices, submissions) and identical Supabase client setup across tens of thousands of independent projects.
For an attacker, that turns exploitation from manual work into a scriptable pipeline. A script that pulls the Vite or Webpack environment variables (VITE_SUPABASE_URL and VITE_SUPABASE_ANON_KEY) from one Lovable app’s JavaScript bundle and queries the PostgREST OpenAPI endpoint for unprotected tables works unchanged against thousands of other Lovable apps. The attacker never has to reverse-engineer an app’s business logic, because the builder stamped out the same backend plumbing everywhere.
Why Lovable’s security scanner is not enough
After the earlier disclosures around CVE-2025-48757 and continued scrutiny of AI-generated schemas, Lovable added defensive tooling: a Security Scan powered by Supabase’s Security Advisor, and an AI-driven Security Reviewer that checks an app for common vulnerabilities before it is published. These are constructive steps and raise the baseline for builders who understand and act on them. But 7,403 sites exposing email tables show that after-the-fact warnings cannot replace secure defaults or professional human review. There are two reasons.
Scanners cannot know what a table is meant to do
A static scanner can detect a plain technical fact: table X has Row Level Security disabled. It cannot reliably tell what table X is for. A table named events or directory_listings may be public on purpose. A table named submissions or summary_logs might hold confidential tenant disputes or passport numbers. An AI reviewer that infers sensitivity from column names still cannot know whether a broad policy, such as letting any logged-in user read every row (TO authenticated USING (true)), is a wanted feature of a shared team workspace or a serious horizontal privilege escalation flaw in a multi-tenant consumer app where Customer A can read Customer B’s invoices.
Publish-time warnings run into user psychology
A non-technical creator has spent hours prompting an app into existence, sees that it works, and clicks Publish. A list of warnings about PostgreSQL Row Level Security policies at that moment produces alert fatigue. The user was told no technical knowledge was needed, so they often lack the mental model to tell a critical blocker from a harmless notice. And if an automatic fix breaks the preview because the app has no complete login flow, the natural reaction is to bypass or undo the restriction so the app works again.
How AI app builders can ship secure-by-default databases
Four changes would move security from an optional review after the build to a fixed constraint at the moment of creation.
Enforce default-deny when generating schemas
Every CREATE TABLE migration an AI coding agent emits should append ALTER TABLE <table_name> ENABLE ROW LEVEL SECURITY; in the same atomic transaction. No table in the public schema should ever exist unlocked, even during early prototyping.
Revoke broad anon privileges by default
Instead of granting ALL privileges on the public schema to the unauthenticated anon role and counting on RLS to block access, programmatic project templates should revoke default anon access (ALTER DEFAULT PRIVILEGES IN SCHEMA public REVOKE ALL ON TABLES FROM anon;). A builder who wants a table, such as a product catalog, readable by unauthenticated visitors would have to switch that specific table to “Public” in a dedicated, plain-language data governance interface.
Turn off PostgREST schema introspection in production
Exposing the full OpenAPI schema at /rest/v1/ to the anon role hands attackers a blueprint of every table and column in the database. Production deployments should strip anon access from introspection endpoints by default.
Use hard deployment gates instead of advisory warnings
Platforms aimed at non-technical users should refuse to publish an app to a public URL if tables with PII columns such as email, phone, passport, ssn, address or payment are accessible to the anon role, or if authenticated policies lack tenant isolation (auth.uid() binding). Overriding the block should take an explicit, multi-step administrative process that spells out the legal and privacy consequences.
Why automated checks still need a human security review
Even with better platform guardrails, the Crissy Field report says automated checks do not replace a professional security assessment. Before any app, hand-written or LLM-generated, moves from prototype to handling real customer, financial or identity data, qualified security engineers should manually verify its access permissions, API interfaces and multi-tenant account boundaries. Those checks need to be repeated after every significant schema or architectural change.









