The Problem Nobody Talks About
Vibe coding tools can generate a full-stack app in minutes. What they can't do is guarantee that app is secure. In February 2026, a Lovable-built app exposed 18,000 users' personal data because the AI generated client-side database queries with no access controls. The developer shipped it in a weekend. The breach took three months to discover.
This isn't an edge case. A Stanford study found that developers using AI assistants produce significantly less secure code than those writing it manually — and are more confident in its security. That overconfidence gap is the real vulnerability.
This checklist covers the 25 most common security failures in vibe-coded applications. It's organized by severity: critical issues that can get you breached today, high-priority items that create exploitable attack surfaces, and medium-priority hardening steps that separate hobby projects from production apps.
Critical: Fix These Before You Show Anyone
1. API Keys Are Not in Your Frontend Code
This is the single most common vibe coding vulnerability. AI tools routinely place API keys, database credentials, and secret tokens directly in client-side JavaScript — where anyone can view them in browser DevTools.
Check: Search your entire codebase for strings like sk-, api_key, secret, password, token, and any hardcoded credentials. Every secret must live in environment variables on the server side only.
Common trap: AI often creates .env files with keys prefixed NEXT_PUBLIC_ or VITE_ — these are exposed to the browser by design. Database credentials, payment keys, and AI API keys should never use public prefixes.
2. Database Queries Are Not Running in the Browser
This is what caused the Lovable breach. If your app connects directly to Supabase, Firebase, or any database from the client side without Row Level Security (RLS), every user can read and modify every other user's data.
Check: Open your browser's Network tab. If you see direct database API calls (e.g., supabase.from('users').select('*') running client-side), you have a problem. All sensitive queries should go through your own server-side API routes.
3. Authentication Actually Works
AI-generated auth often looks complete but has critical gaps: no session expiration, no token refresh, unprotected API routes, or auth checks only on the frontend (bypassed by calling the API directly).
Check: Log in, copy your auth token, log out, then use that token to call your API directly (via curl or Postman). If it still works, your session invalidation is broken. Also test: Can you access /api/admin routes without being an admin? Can you access another user's data by changing an ID in the URL?
4. No Sensitive Data in URLs
AI frequently generates URLs like /user/12345/settings or /api/invoice?userId=67890. If changing that ID shows another user's data, you have a broken access control vulnerability — the #1 item on the OWASP Top 10.
Check: For every URL that contains a user ID, record ID, or resource identifier, try changing it to another valid ID. If you see someone else's data, add server-side authorization checks that verify the requesting user owns that resource.
5. File Uploads Are Validated and Restricted
If your app accepts file uploads, AI-generated code rarely validates file types, sizes, or contents properly. An attacker can upload a .php or .js file disguised as an image and potentially execute code on your server.
Check: Validate file types on the server side (not just by extension — check the actual file header/magic bytes). Set maximum file sizes. Store uploads in a dedicated storage service (S3, Cloudflare R2) rather than your application directory. Never serve uploaded files from the same domain as your app without proper content-type headers.
High Priority: Fix Before Real Users Touch It
6. Input Validation on the Server Side
Client-side validation is a UI convenience, not a security measure. Anyone can bypass your frontend form validation by sending requests directly to your API.
Check: Use a validation library like Zod, Yup, or Joi on your API routes. Validate data types, string lengths, number ranges, and required fields. Reject anything that doesn't match the expected schema.
7. SQL Injection Protection
If your AI generated raw SQL queries with string concatenation (e.g., SELECT * FROM users WHERE id = '${userId}'), you're vulnerable to SQL injection. This lets attackers read, modify, or delete your entire database.
Check: Search for string interpolation inside SQL queries. Use parameterized queries or an ORM (Prisma, Drizzle, Sequelize) that handles this automatically. Never concatenate user input into SQL strings.
8. Cross-Site Scripting (XSS) Prevention
If your app displays user-generated content (comments, profiles, messages), AI-generated code may render it without sanitization — allowing attackers to inject malicious JavaScript that runs in other users' browsers.
Check: Try entering <script>alert('xss')</script> into every text field and see if it executes. Use your framework's built-in escaping (React does this by default with JSX, but dangerouslySetInnerHTML bypasses it). Sanitize any HTML you must render with a library like DOMPurify.
9. Rate Limiting on Authentication Endpoints
Without rate limiting, attackers can attempt thousands of login attempts per second to brute-force passwords. AI-generated auth almost never includes rate limiting.
Check: Try submitting your login form 100 times in rapid succession. If every request succeeds without being throttled, add rate limiting. Use libraries like express-rate-limit or your platform's built-in rate limiting. At minimum: 5 failed login attempts per minute per IP, with exponential backoff.
10. CORS Is Not Set to Allow Everything
AI loves to "fix" CORS errors by setting Access-Control-Allow-Origin: *. This allows any website on the internet to make authenticated requests to your API.
Check: Review your CORS configuration. It should explicitly list your frontend domain(s) only — not *. If your API uses cookies or auth headers, * is especially dangerous because it bypasses the browser's same-origin security.
11. Passwords Are Hashed (Not Stored in Plaintext)
This sounds obvious, but AI has been caught storing passwords in plaintext or using weak hashing algorithms (MD5, SHA-1). If your database is compromised, every user's password is immediately exposed.
Check: Look at your user table. If you can read any password, it's not hashed. Use bcrypt, scrypt, or Argon2 for password hashing. Never use MD5 or SHA-1 for passwords.
12. Error Messages Don't Leak Internal Details
AI-generated error handling often exposes stack traces, database schemas, file paths, and internal server details to the client. This gives attackers a roadmap of your infrastructure.
Check: Trigger errors intentionally (submit invalid data, access nonexistent routes) and check the response. Production errors should return generic messages like "Something went wrong" — never stack traces, SQL errors, or file paths.
13. Dependencies Are Not Wildly Outdated
AI training data includes older package versions. If your AI generated a package.json with dependencies from 2024, those packages may have known vulnerabilities with published exploits.
Check: Run npm audit or pnpm audit. Fix critical and high vulnerabilities. Be especially cautious with packages that handle authentication, encryption, or data parsing.
14. Payment Logic Runs Server-Side
If you're using Stripe (or any payment processor), the price and product details must be validated on the server. If your checkout sends the price from the frontend, an attacker can modify it to $0.01 using browser DevTools.
Check: Open DevTools during checkout. If the request body contains a price or amount field set by the frontend, move that logic to the server. Always create Stripe Checkout sessions or Payment Intents server-side using your product catalog — never trust client-submitted prices.
15. Admin Routes Have Server-Side Role Checks
AI often implements admin panels by hiding the navigation link for non-admin users — but doesn't protect the actual API routes. Anyone who knows the URL can access admin functionality.
Check: As a regular user, try accessing admin API routes directly (e.g., POST /api/admin/users/delete). If it works, add middleware that verifies the user's role on every admin route.
Medium Priority: Harden Before Scaling
16. HTTPS Is Enforced Everywhere
Check: Try accessing your app via http://. It should redirect to https:// automatically. All API calls should use HTTPS. Mixed content (HTTPS page loading HTTP resources) should be blocked.
17. Security Headers Are Set
Check: Use securityheaders.com to scan your site. At minimum, set: X-Content-Type-Options: nosniff, X-Frame-Options: DENY, Strict-Transport-Security (HSTS), and Content-Security-Policy.
18. Session Tokens Are Secure
Check: If using cookies, ensure they have HttpOnly, Secure, and SameSite=Strict (or Lax) flags. If using JWTs, verify they have reasonable expiration times (not 30 days) and are validated on every request.
19. Logging Doesn't Include Sensitive Data
Check: Review your server logs. If you see passwords, API keys, credit card numbers, or personal data in log output, fix your logging to redact sensitive fields. AI-generated console.log(req.body) statements routinely dump credentials to logs.
20. Database Backups Exist
Check: If your database is deleted right now, can you restore it? Set up automated daily backups. Test restoration at least once. If you're on a managed database (Supabase, PlanetScale, Neon), verify that backups are enabled and know how to restore from them.
21. Environment Variables Are Not Committed to Git
Check: Run git log --all --full-history -- .env. If your .env file was ever committed, those secrets are in your git history forever — even if you've since added .env to .gitignore. You'll need to rotate every key that was exposed and use git filter-branch or BFG Repo-Cleaner to purge the history.
22. Third-Party Integrations Use Least Privilege
Check: Review every API key and OAuth scope. Does your app request more permissions than it needs? A read-only integration shouldn't have write access. A notification service doesn't need access to your entire database.
23. Webhook Endpoints Verify Signatures
If you receive webhooks from Stripe, GitHub, or other services, AI-generated handlers often process any incoming request without verifying it actually came from the claimed source.
Check: Verify webhook signatures using the provider's verification library (e.g., stripe.webhooks.constructEvent()). Reject any request with an invalid or missing signature.
24. User Data Deletion Works
Check: If a user requests account deletion, does your app actually delete their data from all tables, file storage, and third-party services? GDPR and similar regulations require this. AI-generated delete handlers often miss linked records, uploaded files, or analytics data.
25. You've Actually Tested as an Attacker
Check: Spend 30 minutes trying to break your own app. Change IDs in URLs. Submit unexpected data types. Call API routes you shouldn't have access to. Upload weird files. Open multiple browser sessions as different users and try to access each other's data. This single exercise catches more real vulnerabilities than any automated scanner.
The Platform Angle: Why Architecture Matters
Many of these vulnerabilities stem from a structural problem: vibe coding tools that generate standalone frontend code leave you responsible for every security layer — auth, database access, API protection, rate limiting, deployment — from scratch.
Platforms that handle infrastructure natively reduce the attack surface by default. For example, Serenities AI ships with built-in authentication (with roles, permissions, and row-level access controls), server-side database queries through its Base layer, managed file storage, and Stripe integration that runs payment logic server-side — all pre-configured. Because the platform owns the infrastructure layer, entire categories of vulnerabilities (client-side database access, plaintext passwords, missing CORS headers) simply don't exist.
The BYOAI model also addresses a subtle security concern: your AI API keys stay in your account settings on the platform, never touching the generated application code. This eliminates the #1 vulnerability on this list (exposed API keys) by architecture rather than vigilance.
That said, no platform eliminates all risk. Input validation, business logic bugs, and third-party integration security still require your attention regardless of what tool you use. Use this checklist even if your platform handles the infrastructure.
A Printable Summary
| # | Check | Severity | Time to Fix |
|---|---|---|---|
| 1 | API keys not in frontend code | Critical | 10 min |
| 2 | No client-side database queries | Critical | 1-4 hours |
| 3 | Authentication actually works | Critical | 1-2 hours |
| 4 | No sensitive data in URLs (broken access control) | Critical | 1-2 hours |
| 5 | File uploads validated and restricted | Critical | 30 min |
| 6 | Server-side input validation | High | 1-2 hours |
| 7 | SQL injection protection | High | 30 min |
| 8 | XSS prevention | High | 30 min |
| 9 | Rate limiting on auth endpoints | High | 15 min |
| 10 | CORS properly configured | High | 10 min |
| 11 | Passwords hashed (not plaintext) | High | 30 min |
| 12 | Error messages don't leak details | High | 30 min |
| 13 | Dependencies not wildly outdated | High | 30 min |
| 14 | Payment logic server-side | High | 1-2 hours |
| 15 | Admin routes have role checks | High | 30 min |
| 16 | HTTPS enforced | Medium | 10 min |
| 17 | Security headers set | Medium | 15 min |
| 18 | Session tokens secured | Medium | 15 min |
| 19 | Logging doesn't include secrets | Medium | 20 min |
| 20 | Database backups exist | Medium | 15 min |
| 21 | Env vars not committed to git | Medium | 10 min |
| 22 | Third-party integrations use least privilege | Medium | 20 min |
| 23 | Webhook signatures verified | Medium | 15 min |
| 24 | User data deletion works | Medium | 1-2 hours |
| 25 | You've tested as an attacker | Medium | 30 min |
The Bottom Line
AI doesn't write insecure code because it's bad at coding. It writes insecure code because security was never part of your prompt. The AI optimizes for "make it work" — not "make it safe." That gap is your responsibility.
The good news: most vibe coding vulnerabilities fall into predictable categories. Run through this checklist once, fix what fails, and you'll be more secure than 90% of AI-generated applications shipping today.
The better news: you don't have to memorize all 25 items. Bookmark this page, run through it before every launch, and build the habit of asking "how could someone abuse this?" every time your AI generates a new feature.
Security isn't a feature you add at the end. It's a checklist you run before the beginning.