From Vibe Coding to Production: The Checklist That Stops Data Leaks
Vibe coding to production safely: the 25-point checklist covering RLS, secrets, ownership checks, and rate limits that stops AI-built data leaks.
Pare de configurar. Comece a construir.
Templates SaaS com orquestração de IA.
Taking a vibe-coded app to production safely comes down to four checks you can verify in under two hours: turn on Row Level Security on every database table, move every secret to the server, add an ownership check to every API endpoint, and rate-limit your login and signup routes. Two AI-built apps, Moltbook and Lovable, leaked a combined 1.5 million API tokens and tens of thousands of user records in early 2026 because they shipped without those four things. This post names the exact breaches, the exact root causes, and gives you a copy-paste 25-point checklist that closes every gap.
Pare de configurar. Comece a construir.
Templates SaaS com orquestração de IA.
What "vibe coding" actually means (and why it leaks)
Vibe coding means describing an app in plain English and letting an AI tool write the code, often without reading much of it. The problem: the AI writes code that runs, not code that is safe. An app can work perfectly in a demo and still let a stranger read your entire user database.
If you are about to put real names, emails, or payment details into a vibe-coded app, the gap between "it works" and "it is safe" is exactly where the leaks happen. The same four mistakes caused every breach below, and all four are quick to fix.
The breaches, named
Moltbook (January 31, 2026). A social app built with reportedly zero hand-written lines of code exposed around 1.5 million API tokens and gave anyone full unauthenticated read and write access to its Supabase database. Root cause: Row Level Security was never turned on, and the database key was hardcoded into the client-side JavaScript (the code that runs in every visitor's browser, where anyone can read it). This is the canonical vibe-coding breach.
Lovable (February 26, 2026). An inverted authentication check exposed 18,697 records, including 10,505 enterprise users. The guard was written backwards: it blocked legitimate users and let unauthorized ones through. Tracked publicly as CVE-2025-48757.
Lovable (April 2026). A second issue re-exposed chat histories that contained API keys and personal data through a public project endpoint. The flaw was BOLA (more on that below). Lovable reportedly first described the behavior as "intentional".
| Incident | Date | Platform | Records Exposed | Root Cause | RLS + fix would have stopped it |
|---|---|---|---|---|---|
| Moltbook breach | Jan 31, 2026 | Supabase | ~1.5M API tokens | Missing RLS + hardcoded key in client JS | Yes |
| Lovable February breach | Feb 26, 2026 | Lovable | 18,697 user records | Inverted auth logic, no ownership check | Partially |
| Lovable April breach | Apr 2026 | Lovable | Chat histories with API keys + PII | BOLA on public project endpoint | Yes |
| VibeAppScanner scan | Ongoing | Multiple | 10.3% of 1,645 apps open to anonymous reads | Missing RLS | Yes |
The four failure modes behind every breach
-
RLS disabled or missing. Row Level Security is a Postgres feature that says "a user can only see their own rows". Without it, one read query returns everyone's data. Reported research found RLS gaps behind roughly 83% of Supabase exposures, and a scan by VibeAppScanner found 10.3% of 1,645 Lovable-built apps had tables readable with no login at all.
-
Secrets hardcoded in client-side code. A secret is any key that proves who your server is. If it sits in browser code, anyone can copy it. One analysis of 20,000 AI-generated apps found the literal string
supersecretkeyin 1,182 of them. -
No ownership check on API endpoints (BOLA). BOLA stands for Broken Object Level Authorization. In plain terms: a logged-in user changes an ID in a request (say
/api/orders/123to/api/orders/124) and your app hands back someone else's data. This was the root cause of both Lovable incidents. -
No rate limiting on auth routes. Without a cap on attempts, an attacker can guess passwords or spam signups thousands of times a minute. Login, signup, and password-reset are the routes that need it most.
The confidence-competence gap
This is the uncomfortable part. Nearly 80% of developers report believing AI tools write more secure code than humans do (reported, Snyk survey). A Carnegie Mellon study found only 10.5% of AI-generated code was actually secure. Separate research found AI-assisted developers introduce security findings at roughly 10 times the rate of their peers. Vibe coding feels safe because it is fast. The speed is exactly the problem: you ship before you check.
The Supabase RLS fix, step by step
This is the single highest-value check. Three steps.
-
Turn on RLS. In the Supabase dashboard, open Authentication, then Policies, pick your table, and click Enable RLS. The moment you do, the table returns nothing until you add a policy. That is correct: deny by default.
-
Add an ownership policy. Run this SQL, replacing
your_tableanduser_idwith your names:
ALTER TABLE your_table ENABLE ROW LEVEL SECURITY;
CREATE POLICY "users can only see own rows"
ON your_table
FOR ALL
USING (auth.uid() = user_id);auth.uid() is the ID of whoever is logged in. The policy says: only return rows where the row's owner equals the logged-in user.
- Verify with the anon key. Query the table using your public anon key with no login. It should return zero rows. If it returns data, RLS is not protecting that table. Test every table, not just one.
If you want this enforced for you instead of remembered by you, the $29 Code Kit (a build system, or harness, for Claude Code) ships with row-level security on every table by default, so an unprotected table is something you would have to actively undo rather than forget to add.
The 25-point checklist
Work top to bottom. Do not ship without the Critical tier done.
Critical (do these or do not launch):
- RLS enabled on every database table.
- An ownership policy (
auth.uid() = user_id) on every user-data table. - Anon-key test returns zero rows on every table.
- Every API key and secret lives in server-side environment variables.
- Zero secrets in client-side JavaScript (search your bundle for "key" and "secret").
- Every API endpoint checks the record owner matches the logged-in user.
- Auth guard logic tested both ways: legitimate users get in, others do not.
High: 8. Rate limiting on login. 9. Rate limiting on signup. 10. Rate limiting on password reset. 11. HTTPS-only, no plain HTTP routes. 12. Session tokens expire and refresh correctly. 13. Service-role or admin keys never reach the browser. 14. Password reset tokens are single-use and time-limited.
Medium: 15. Input validation on every form and API field. 16. SQL handled through parameterized queries, never string-concatenation. 17. Dependency scan for hallucinated packages (around 20% of AI-generated code references packages that do not exist or are typosquatted). 18. File uploads checked for type and size, stored with per-user access. 19. No secrets committed to git history. 20. Email and webhook signatures verified.
Low: 21. Error messages do not reveal stack traces or table names to users. 22. Logging captures auth events without storing passwords. 23. CORS headers restricted to your own domains. 24. Security headers set (CSP, X-Frame-Options). 25. A plan to re-run this list after every major feature.
For deeper context on a few of these, see our related guides on row-level security, Claude Code subagents, and the CLAUDE.md file that keeps an AI build inside your rules.
FAQ
Is a vibe-coded app safe to use with real user data?
Not by default. CVE-2025-48757 found 10.3% of analyzed Lovable-produced apps had Supabase tables readable without authentication. Before handling real user data you need to manually enable RLS, move secrets to the server, add ownership checks to every API endpoint, and rate-limit your auth routes.
How do I enable Row Level Security in Supabase?
In the Supabase dashboard go to Authentication, then Policies, select your table, and click Enable RLS. Then add a policy such as CREATE POLICY "users can only see own rows" ON your_table FOR ALL USING (auth.uid() = user_id). Verify it by querying the table with your anon key: it should return zero rows for unauthenticated requests.
What is a BOLA vulnerability in AI-generated apps?
BOLA (Broken Object Level Authorization) means your API returns records belonging to other users when a logged-in user changes an ID in the request. It was the root cause of the Lovable February 2026 breach that exposed 18,697 records. The fix: every endpoint must check that the requested record's owner ID matches auth.uid() before returning data.
What is the minimum vibe coding security checklist before launch?
Four critical checks: (1) RLS enabled on every database table, (2) all API keys in server-side environment variables and never in client code, (3) ownership validation on every API endpoint that touches user data, and (4) rate limiting on login, signup, and password-reset routes. Everything else is high or medium severity and can follow.
Pare de configurar. Comece a construir.
Templates SaaS com orquestração de IA.
State of Vibe-Coded SaaS Security (2026 Data)
Vibe coding security statistics from 2026 scans: 5,600 apps, 2,000+ vulnerabilities, 45% OWASP failure rate, and the Moltbook breach.
Vibe Coding vs Vibe Engineering vs Agentic Engineering: The 2026 Glossary
Vibe engineering, vibe coding, and agentic engineering defined plainly, with origins, a comparison table, and when to use each in 2026.