We Teardown AI-Generated Web Apps: The 3 AI-Specific Security Mistakes

Vergate Team3 min read

AI code generators are incredible at producing working apps fast. They are also incredibly consistent at repeating the same security mistakes — because those mistakes are baked into the patterns they were trained on.

We ran our audit engine — now with three new AI-specific checks — against a set of production apps built with AI assistance. The results clustered into three distinct failure modes that rarely appear together in hand-written code.

#Finding 1: Supabase wired client-side with RLS as an afterthought

The most common pattern in vibe-coded backends: supabase.createClient(url, anonKey) right in the browser, tables created with Row Level Security disabled, and the app relying on client-side filters to keep data private.

Why it ships: Supabase's quickstart templates create tables with RLS on, but the moment you let the AI "add a simple settings table" it generates create table settings (...) with no alter table ... enable row level security, and the AI happily reuses that no-RLS pattern everywhere.

What the check does: finds .supabase.co references in page source, probes /rest/v1/ unauthenticated to confirm the API surface is reachable, and — the definitive catch — detects a service_role JWT leaked into client code (credential-level access that bypasses RLS entirely).

#Finding 2: AI API keys shipped to the browser

Vibe-coded apps often call Anthropic / OpenRouter / Groq / Perplexity directly from the frontend — either because "it's simpler" or because the AI added a serverless function that doesn't expose secrets but then hardcoded the key anyway.

Because AI providers bill per token, a leaked key is an open faucet: anyone who reads the page source can authenticate as your app, burn your quota, read your conversation history, and exfiltrate your prompts.

The new api_key_leaks check scans page source and linked JS for AI-provider key formats browsers should never see: sk-ant- (Anthropic), pplx- (Perplexity), gsk_ (Groq), CO- (Cohere), hf_ (Hugging Face), r8_ (Replicate), sk-or-v1- (OpenRouter), lsv2_pt_ (LangSmith), and Supabase's sb_secret_ admin keys — complementing the existing secrets check rather than duplicating it.

#Finding 3: Login forms generated with insecure defaults

The quiet one: forms that submit passwords over plain http://, password fields inside method="get" forms (credentials land in URLs, history, and server logs), and autocomplete="off" on password fields (which forces users back to weak, reused passwords because their manager is disabled).

None of these fail loudly. The page works, the login works, and nobody notices for weeks — until someone reads the server logs and sees a URL with a password in it.

The new insecure_auth_defaults check inspects every form on the page and flags exactly these patterns, plus hardcoded default credentials (password: "admin", "changeme", "123456") that generator templates love to leave in place.

#The pattern behind all three

Hand-written code shares mistakes too — but AI-generated code shares them with consistency. The same training data that taught the model how to scaffold a Supabase client also taught it the quickstart's most insecure variation. That's why a scanner needs checks that are specific to the AI stack: the classic header/TLS checklist isn't what breaks these apps.

#How to fix it (the short version)

  1. Supabase: enable RLS on every table (select * from pg_tables where rowsecurity = false will show you the gaps), never put a service_role key in the browser, and keep the anon key as the only client-visible credential.
  2. AI keys: move every provider key to server-side environment variables and proxy the calls through your backend. The browser should never know a key exists.
  3. Forms: force HTTPS on all form actions, use method="post", and set autocomplete="current-password" / "new-password". Delete hardcoded default credentials on sight.

Every finding from these checks ships with a copy-paste fix prompt — open it in your AI assistant and it will give you the exact diff.

Frequently asked questions

How were these AI-generated apps selected?

We scanned production web apps that were built substantially with AI assistants (sites that disclose it, apps with tell-tale bot-generated boilerplate, and demo apps from AI code generators). The selection was non-random — we targeted exactly the patterns the new checks are designed for.

Are these the same as the top-4 mistakes from your 50-app audit?

No. The 50-app audit covered headers, stack traces, staging endpoints, and TLS — the classic misconfiguration layer. This teardown is about the AI-specific layer: code that wires in cloud providers (Supabase), external API keys (Anthropic, OpenRouter, etc.), and auth defaults in a way a human rarely does but a code generator happily does.

What's the most dangerous finding?

The leaked AI API keys. Because every AI provider charges per token, a leaked key is not just a data breach — it's an open billing faucet. A single sk-ant- (Anthropic) or sk-or-v1- (OpenRouter) key exposed in client code can burn thousands of dollars overnight and is trivially extracted by anyone who views the page source.

Can I test my own site for these issues?

Yes. Run a free scan at vergate.dev/free-scan or with the MCP server — the engine now includes supabase_rls_exposure, api_key_leaks, and insecure_auth_defaults in every passive scan, with a fix prompt for every finding.

Keep reading