You Vibe-Coded an App. Now Don't Get Pwned.
Bots find a leaked OpenAI key in under four minutes. Lovable apps shipped with wide-open Supabase databases. The Tea breach. Every disaster has the same shape, and avoiding it doesn't take a security degree.
Bots find your leaked OpenAI key in under four minutes.
One small startup's normal monthly OpenAI bill was $400. Their key sat in a public GitHub repo for eleven days. The next invoice was $67,000. Automated bots scan every public commit, validate any AI key they find, list it on a marketplace, and sell it for $30. The buyer proxies through it anonymously, running Claude Opus or GPT-4 at full tilt on the original owner's quota.
That's not the worst case. A researcher named Matt Palmer scanned 1,645 apps built on Lovable in 2025. 170 had wide-open Supabase databases anyone could read in a browser. He bypassed Stripe on a live, paying product by sending one request: "payment_status": "paid". CVSS 9.3. Lovable's own Security Scanner had given those apps a green checkmark.
Then there's Tea, the women-only safety app with 1.6 million users that stored government IDs in an unprotected cloud bucket. 72,000 photos, including 13,000 IDs, hit 4chan within hours. One plaintiff was a single mother in Nevada using Tea while fleeing a domestic abuser. The breach put her at direct physical risk.
If you're shipping AI-built apps and don't know what an env var is, this post is for you. You don't need a security degree. You just need to know what to check, and your agent does the actual work.
Every disaster comes down to one of two failures.
Imagine your app is a hotel. The lobby is your frontend. The back office is your backend. The records room is your database. Two kinds of keys exist. The lobby key (in Supabase, the anon key) opens the front door. The master key (the service role key) opens every room including the records room.
Almost every horror story you'll read about boils down to one of two failures. First: the master key got into the lobby. Someone committed a service-role key, an OpenAI key, or a Stripe secret key into a frontend file or a public repo. Bots find it in minutes.
Second: there were no room-key rules, so anyone with the lobby key could walk into anyone's room. In Supabase, this is what happens when Row Level Security is off. The anon key is supposed to be safe in your frontend only because RLS enforces who can read what. Without RLS, the anon key alone unlocks every row in every table.
Lovable's CVE-2025-48757 is failure two. The Replit AI that deleted Jason Lemkin's production database despite an explicit code freeze, then generated 4,000 fake records to cover the gap, is failure one. The Tea app left government IDs in a folder online with no lock. Same pattern. Different headline.
What to actually check before you ship.
If you're shipping in the next week, here are the six things that matter most. Each one closes the door on a real breach class, not a theoretical concern.
Secrets in your code. If your AI ever wrote apiKey = "sk-proj-..." and that file is in your repo, your key is in your code. Bots will find it. Every API key, every Stripe secret, every Supabase service role key belongs in environment variables. Vercel and Netlify both inject env vars at runtime. Setting one takes 90 seconds.
Row Level Security on every Supabase table. Without RLS, your anon key is enough for any visitor to read your entire database. Supabase ships with RLS off by default on new tables. This is exactly how 170+ Lovable apps got owned. Turn it on, and write policies that match your real-world ownership model: user_id matches auth.uid(), tenant_id matches a memberships table, public reference data stays read-only.
Login that you didn't write yourself. Use Supabase Auth, Clerk, Auth0, or Firebase Auth. The list of ways to get login wrong is long and unforgiving. Even pros mess it up. A hosted auth provider handles password hashing, sessions, two-factor, password resets, and the dozen edge cases you'd never think to check.
Rate limiting on expensive endpoints. Without it, anyone can hit your most expensive endpoint (the one calling OpenAI) on repeat and run up your bill until you're broke. Upstash Ratelimit is a few lines of code. It's the single biggest win you can grab today.
Stripe webhook signature verification. When Stripe sends your app a webhook saying "this user just paid," verify the signature. Without verification, anyone can send a fake POST to your webhook URL claiming any user paid for anything. They get the paid features for free. You get the bill. Same pattern that broke 170+ Lovable apps.
Input validation with Zod. Define what shape inputs should be in: a string, an email, a number between 1 and 100. Zod kicks out anything that doesn't match before it touches your database. SQL injection, type-confusion bugs, and {"isAdmin": true} mischief all close on this single change.
Open your agent. Paste these prompts.
Reading the answers above is faster than running a security tool. Pasting a prompt is faster than reading the answers. Each prompt below is engineered for a coding agent: explicit scope, regex patterns, output format specs, edge case handling. Pasting one at Cursor, Lovable, Bolt, or Claude Code produces specific findings, not generic "review my code" hand-waving.
The full set lives in the next post: 10 Copy-Paste Security Prompts for Your AI Agent. Audit secrets. Add RLS. Set up env vars. Scrub git history. Rate limit. Validate input. Audit your auth flow. Verify Stripe webhook signatures. Find frontend-only access controls. Pre-flight check before deploying.
Open the post. Open your agent. Pick the one that matches your worry. Paste. Read what comes back. Fix every CRITICAL.
Set a calendar reminder for next Monday: five-minute security ritual. Cost dashboards, auth provider logs, GitHub Secret Scanning alerts, deploy logs, Have I Been Pwned. Five minutes, every week. That's the job.
Run Composed on your last 10 PRs.
Apply for design partner access and we’ll show which findings are real, exploitable, and worth fixing — free.
Run it on 10 PRs →