All posts
6 min read

A Security Checklist for Vibe-Coded Apps

AI-built apps fail security in predictable ways: open databases, keys in the browser, authorization checked only in the UI. A practical checklist for non-security people — what to check, how to test it yourself, and what to fix before real users arrive.

securityno-codedeploymentAI agents

AI coding tools are very good at making things work. They're much less reliable at making things safe, because safety is mostly about what should fail — and a demo only tests what should succeed.

The good news is that vibe-coded apps fail security in a small number of predictable ways. You don't need to be a security engineer to check for them. You need a list, a second test account, and an hour.

Here's the list, roughly in order of how often each problem shows up and how much damage it does.

1. The database is open to anyone

The most common serious problem, by a distance.

Apps built on Supabase or Firebase talk to the database directly from the browser, using a key that is public by design. The only thing stopping a stranger from reading your whole users table with that key is the database's access rules — row-level security (RLS) in Supabase, security rules in Firebase.

In 2025, a researcher found that around 170 of roughly 1,600 apps sampled from one popular AI builder exposed personal data to anyone, because RLS was missing or too permissive. It was tracked as CVE-2025-48757, and the pattern is common far beyond that one tool.

Check:

  • RLS is enabled on every table — including ones you think aren't sensitive.
  • Each table has policies limiting reads and writes to the right rows. A policy that allows everything (true) is the same as no policy.
  • Storage buckets have policies too.

Test it yourself: create two accounts. Signed in as the second, try to load the first account's records — change an ID in the URL, or ask the AI to write you a quick script using the public key. Then try signed out. If you can see anything you shouldn't, so can everyone else.

2. Secret keys are in the browser

AI tools often paste API keys into the code, or put them in environment variables with a VITE_ or NEXT_PUBLIC_ prefix — which ships them to every visitor.

Check:

  • No AI API keys, payment secret keys, email API keys, or database service-role keys in frontend code.
  • Open your live site's developer tools and search the loaded JavaScript for the first few characters of each secret. Nothing should match.
  • .env files are in .gitignore and not in git history.

If a secret has already been exposed, rotate it — deleting it from the code doesn't un-leak it. Full guide: How to Keep API Keys Out of an AI-Built App.

3. Authorization lives only in the interface

A classic AI-generated pattern: the admin page is hidden from non-admins in the menu, but the API behind it doesn't check who's asking. Hiding a button is not a permission check.

Check:

  • Every API route and server function verifies the user and checks they're allowed to do the specific thing — on the server, every time.
  • Record IDs in URLs (/invoices/1042) can't be changed to see someone else's record.
  • Admin actions check for an admin role on the server.

Test it: as a normal user, copy the request an admin page makes (developer tools → Network tab) and replay it. It should fail.

4. Authentication is home-made

AI will cheerfully write a login system from scratch: password hashing, sessions, reset emails. Every one of those is a place for subtle, serious mistakes.

Check:

  • Sign-in uses an established provider or library — Supabase Auth, Clerk, Auth0, Firebase Auth, NextAuth/Auth.js — not custom code.
  • Password reset links expire and work only once.
  • Email verification is on if accounts unlock anything valuable.

5. Payments trust the browser

If the browser tells your server "the user paid $49" and the server believes it, a user can pay $0.

Check:

  • Prices are set on the server or in the payment provider — never sent from the browser.
  • Access is granted from the provider's webhook, with the webhook signature verified — not from the "payment succeeded" page loading.
  • You've tested a failed payment and a refund, not just a successful payment.

6. User input is trusted

Check:

  • Database queries use the library's parameterised queries or ORM — no user text concatenated into SQL.
  • User-supplied content displayed to other users is escaped (most frameworks do this by default; watch for AI code that uses "dangerously set HTML" or similar to render user text).
  • File uploads check type and size, and uploaded files aren't served from your main domain as executable content.

7. Nothing limits abuse

Check:

  • Sign-up, login, and password reset are rate-limited.
  • Any endpoint that costs you money — AI calls, SMS, email — requires login and has a per-user limit.
  • Every paid API provider has a spending cap set in its dashboard.

An unprotected endpoint that calls an AI model is a public, free AI service that you're paying for.

8. Production is reachable from development

Check:

  • Development and testing use a separate database from production.
  • AI agents working on the code never hold production credentials.

We explain why in How to Stop an AI Agent From Deleting Your Production Database.

9. There's no way back

Security incidents include your own mistakes. Check:

  • The database has automated backups, and you've restored one at least once.
  • The code is in git, pushed to GitHub, so any change can be reverted.
  • You'd find out if something broke — error alerts, uptime monitoring — before a user emails you.

10. Dependencies are stale or invented

Check:

  • Every package the AI added actually exists and is the one you meant — AI tools occasionally suggest package names that don't exist, which attackers can register.
  • Dependabot or similar is enabled to flag known vulnerabilities.

How to use this list with an AI

The AI that built the app can help audit it, as long as you ask specific questions rather than "is this secure?" (it will say yes). Try:

  • "List every table and its RLS policies. Flag any table without RLS or with a policy that allows all rows."
  • "List every API route and exactly how each one checks the user's identity and permissions."
  • "Find every environment variable exposed to the browser and tell me what each one contains."

Then verify the answers by testing, because the most dangerous bug is the one the AI is confident isn't there.

Where to draw the line

This checklist catches the common, high-impact failures. It isn't a penetration test. If your app handles payments at volume, health data, or anything regulated, pay a security professional to review it before launch. For everything else, these ten checks put you ahead of a surprising share of apps already live.


EasySpawn runs each project in an isolated container with managed secrets, a separate managed database, and daily backups — so the infrastructure layer is handled, and you can focus the checklist on your app. See how it works for AI-built apps or join the waitlist.

Related: How to Keep API Keys Out of an AI-Built App · How to Deploy a Lovable App to Production

Keep reading