Why We Don't Publish Names
Every case in this post is real. None of them are named. We contact affected app owners privately, give them time to patch, and only publish identifying details with consent — or never.
If you think one of these cases is your app, email [email protected]. We will send the full report privately, walk you through the fix, and never publish identifying details without your consent.
The Methodology
On April 14, 2026 we ran vibeAudit against 40 production apps in a single day. Targets were pulled from public AI-builder showcase pages — Lovable, bolt.new, Cursor, v0, Claude Code. One read-only scan per app. We used the same public anon key each app already ships in its own JavaScript bundle. No exploits written, no data exfiltrated, no rate limits touched. Every finding was evidence-verified against a live endpoint before it counted.
The Numbers
- 40 apps scanned
- 30 CRITICAL findings across 8 targets
- 111 total findings across all severities
- 6 apps with 3 or more CRITICALs stacked on a single target
- 1 shipped a Supabase service_role JWT directly in the client bundle
None of these required a zero-day. None required a custom tool. The anon key was right there in the page source.
Pattern 1: Row Level Security Disabled
The most common finding, by a wide margin. A Lovable job-matching SaaS left 20+ tables open to anon reads — listings, profiles, and contact metadata all returned in one GET. A Lovable social content app returned every user's email in one request against the users table. A contributor-driven content platform had six separate tables world-readable, linking usernames to submission timestamps and breaking the pseudonymity the site advertised.
The pattern is always the same. A developer creates tables in the Supabase dashboard. RLS is off by default on new tables. The app works. Nothing warns them that "works" and "safe" are different things.
Pattern 2: Secrets in the Client Bundle
A Lovable real-estate CRM shipped a Supabase JWT with role=service_role in its compiled JavaScript. That key bypasses every RLS policy on every table in the project. Full read, full write, full delete, every bucket. Anyone who viewed the site source had god mode.
Service-role keys belong on servers. They ended up in the browser because the AI generator didn't know the difference between a public anon key and a privileged one — they look identical until you decode them.
Pattern 3: PII Tables Left Open
A vertical directory SaaS returned emails, phone numbers, and street addresses across three separate provider tables. A members-only community app returned member contact data plus booking history — enough to reconstruct who showed up where, and when. A file-processing utility stacked eight CRITICAL findings on one target, including an XXE in the upload parser and multiple API routes with zero authentication.
These apps are not side projects. They have paying users. They are being found by Google.
Why This Keeps Happening
AI code generators optimize for does it render, not is it safe. The feedback loop during development is visual: the component appears, the button works, the data shows up. RLS misconfiguration produces no visible symptom. A service-role key in the bundle produces no visible symptom. An unauthenticated API route produces no visible symptom — until someone hits it on purpose.
The generators don't test for what doesn't render. Neither does the developer, because they shipped in a weekend and moved on.
What to Do Right Now
Check 1: Search your bundle for secrets.
# Open your deployed app, F12, Sources tab.
# Search the JS files for:
service_role # Supabase god-mode key
sk_live_ # Stripe secret key
AKIA # AWS access key
sk- # OpenAI key
-----BEGIN # Private key of any kind
postgres:// # Direct DB connection string
# Found one? Rotate it. Today. Then move it server-side.
Check 2: Hit your own tables with the anon key.
# Grab the anon key from your app's JS bundle.
curl "https://YOUR_PROJECT.supabase.co/rest/v1/users?select=*" \
-H "apikey: YOUR_ANON_KEY"
# If it returns rows, RLS is off on that table.
# Fix: ALTER TABLE users ENABLE ROW LEVEL SECURITY;
# Then write policies. "Enabled with no policies" = deny all.
Check 3: Run a full scan.
Paste your URL into vibeAudit. 30 seconds, read-only, no signup. The scanner uses the same techniques that produced the 111 findings in this post.
If This Is Your App
Email [email protected]. We will send the full report privately, walk you through the fix, and never publish identifying details without your consent. No name-and-shame. No press. Just the report and a path to patched.