The vibe-coding security checklist: 12 things to verify before your AI-built app goes live
Row-level security, secrets in the client bundle, permission checks in the browser, unverified webhooks. These are the security gaps we find most often in apps built with Lovable, Cursor, Bolt, v0 and Replit, and how to close each one.
- Security
- Vibe coding
- Supabase
- Checklist
Apps built with Lovable, Cursor, Claude Code, Bolt.new, v0, Replit, Windsurf, GitHub Copilot or Base44 tend to look finished long before they are safe. Nothing in the demo hints at what is missing underneath. We take security seriously and check it on every project we touch, and the gaps below are the ones we find most often in AI-generated code. Work through all twelve before you let real users in.
1. Row-level security is actually enabled, and the policies exist
What to look for. If you use Supabase or talk to Postgres directly from the client, open the database and check every table that holds user data. Is row-level security switched on? Are there policies, and do they restrict rows to the owning user rather than allowing everything?
Why AI tools get it wrong. The tools generate the table and the query, and the query works in the demo because there is one user. Enabling RLS makes the demo fail until policies are written, so the model either skips it or writes a permissive policy to make the error go away.
How to fix it. Enable RLS on every table exposed to the client. Write policies per operation, test them with two accounts, and treat a table with RLS disabled as public.
2. No secrets in the client bundle
What to look for. Search the codebase for hardcoded API keys, and search for environment variables prefixed with NEXT_PUBLIC_ or the equivalent in your framework. Anything with that prefix is shipped to every browser. Then open the deployed site, view the JavaScript, and search for the first few characters of your keys.
Why AI tools get it wrong. The fastest way to make a third-party call work is to put the key where the call is, and the call is often in a component. The tool does not distinguish between a public anon key and a service key that bypasses every rule.
How to fix it. Move privileged calls to server routes or functions. Keep only truly public keys in client-side variables. Rotate anything that has ever been in a bundle, because you should assume it has been scraped.
3. Authorisation is checked on the server, not just in the browser
What to look for. Find every place the interface hides something based on who is logged in, then call the underlying API directly with a tool like curl. If the data comes back, you have no authorisation.
Why AI tools get it wrong. Hiding a button is visible progress. A server-side check is invisible until someone abuses its absence, so it rarely gets prompted for.
How to fix it. Every server route, function and database policy must verify identity and permission itself. The interface is a convenience, never a control.
4. Admin routes and leftover debug endpoints are locked down
What to look for. List every route. Look for admin pages, "seed" or "reset" endpoints, test pages and anything that was useful during development. Try each one while logged out.
Why AI tools get it wrong. Debug endpoints get generated to solve a problem in the moment and are never removed. Admin pages are protected by obscurity because that is what the prompt implied.
How to fix it. Delete what you do not need. Put what remains behind explicit server-side role checks, and log access to it.
5. Webhooks verify their signatures
What to look for. Open the Stripe, payment gateway or messaging webhook handler. Does it verify the signature header against your webhook secret before doing anything? Or does it trust whatever arrives?
Why AI tools get it wrong. Signature verification is the step that makes local testing awkward, so it is the step that gets stubbed out.
How to fix it. Verify signatures with the provider's library on the raw request body, reject failures, and make handlers idempotent so a replayed event cannot mark the same order paid twice.
6. No queries are built by string concatenation
What to look for. Search for SQL or query strings assembled with plus signs, template literals or format functions that include user input.
Why AI tools get it wrong. String building is the simplest code that produces a working query, and the tool has no reason to prefer the safer version unless told.
How to fix it. Use parameterised queries or your ORM's query builder everywhere. Treat any string-built query as a bug even if it "only" takes an ID.
7. Uploads are validated and buckets are not public by accident
What to look for. Check what file types and sizes uploads accept, where files land, and whether the storage bucket or folder is readable by anyone with the URL. Try uploading a script file renamed with an image extension.
Why AI tools get it wrong. Public buckets make previews work immediately. Validation is friction.
How to fix it. Validate type and size on the server, generate your own file names, serve private files through signed URLs, and review bucket policies as carefully as database policies.
8. Public endpoints are rate limited
What to look for. Login, sign-up, password reset, contact forms, search and anything that calls a paid AI or email API. Can you hit them a thousand times in a minute from one machine?
Why AI tools get it wrong. Rate limiting is never part of the feature request. It only matters once someone hostile, or merely curious, finds the endpoint.
How to fix it. Add per-IP and per-account limits at the platform or middleware level, put bot protection on forms, and set hard spending caps on every third-party API key.
9. Dependencies are pinned, current and maintained
What to look for. Run your package manager's audit command. Look for packages with no releases in years, packages with a single maintainer that do something security-critical, and version ranges wide enough to pull in a compromised release.
Why AI tools get it wrong. The model suggests whatever package it saw most in training, which may be abandoned or superseded, and it rarely pins versions.
How to fix it. Commit a lockfile, pin versions, fix or replace anything flagged, and add automated dependency updates so this does not decay again.
10. Logs do not contain personal data or secrets
What to look for. Read the logging output for a full user journey. Look for full request bodies, tokens, passwords, ID numbers, card details and email addresses.
Why AI tools get it wrong. Logging the whole object is the quickest way to debug, and the code that was written to debug is still running in production.
How to fix it. Log identifiers, not payloads. Redact known sensitive fields centrally. Remember that under POPIA, a log file full of personal information is still personal information.
11. Backups exist and you have restored from one
What to look for. Is the database backed up automatically? When was the last backup? Has anyone ever restored it to a fresh instance and confirmed the app runs against it?
Why AI tools get it wrong. Backups are a hosting decision, not a code decision, so no prompt ever produced one.
How to fix it. Turn on automated backups with point-in-time recovery where the platform offers it, and do a restore drill before launch rather than after an incident.
12. CORS, cookies and sessions are configured deliberately
What to look for. Check whether the API allows requests from any origin. Check that session cookies are marked secure, HTTP-only and with a sensible same-site setting. Check how long sessions live and whether logging out actually invalidates them.
Why AI tools get it wrong. A wildcard origin makes the cross-origin error disappear. Default cookie settings vary by library, and the model does not know which one you ended up with.
How to fix it. Allow only the origins you own, set cookie flags explicitly, and test logout and expiry with a second browser.
Before you ship
If several of these made you uncomfortable, that is normal, and it is fixable without starting over.
Where QLTech fits
We audit AI-built apps at a fixed price, close exactly these gaps, and hand back a codebase you can keep building on. Read why vibe-coded apps break in production for the wider picture, or start with our AI app rescue service.