From Prototype to Product
Vibe Coding Security Risks: What to Check Before You Launch
A plain-language pre-launch security checklist for founders with AI-generated code: auth, secrets, data exposure, and dependencies — covering real vibe coding security risks.
If you used Cursor, Lovable, Bolt, or a similar tool to build your app, congratulations — you shipped something real without a six-figure dev budget. That matters. But before you point a real domain at it, send it to customers, or store any data that isn't yours to lose, you need to do a basic security pass. AI-generated code has a specific profile of weaknesses, and most of them are fixable without a full rewrite. This guide walks through the ones that actually cause founders problems.
Why AI-Generated Code Has a Different Risk Profile
Vibe coding tools are remarkably good at generating working code quickly. They're trained on millions of examples, and they pattern-match to produce something that runs. The problem is that a lot of the training data reflects common patterns — including common insecure patterns. The model doesn't understand what's at stake if a credential leaks or a database query is injectable. It's assembling plausible code, not reasoning about threat models.
There's also an intent gap. When you're iterating quickly on a prototype, the AI is trying to give you something functional. Environment variable handling, input validation, and access controls often get scaffolded in ways that work locally but aren't production-ready. The AI won't flag this. It'll generate what you asked for and move on.
I've seen this pattern repeatedly in our work at Atlas Atlantic: a founder has a genuinely useful product, a paying pilot customer waiting, and a codebase that has hardcoded API keys checked into GitHub. That's not a hypothetical — GitHub's secret scanning catches thousands of exposed credentials every day, and a meaningful portion come from founders who moved fast and didn't know what to look for.
The core risk in plain terms
AI-generated code is optimised to run, not to be secure. It won't warn you when it hardcodes a secret, skips an authorisation check, or uses a vulnerable library. You have to check these things yourself — or have someone check them for you — before real users and real data enter the picture.
1. Secrets and API Keys: The Most Common and Most Fixable Risk
This is the one that bites founders most often, and it's almost entirely preventable. When you're prototyping with an AI coding tool, it's common to paste in credentials to get something working — an OpenAI key, a Stripe secret, a database password. The AI uses it in the code. You commit the code. You push to GitHub. The key is now public, possibly permanently (git history is forever unless you explicitly purge it).
Before launch, run a secret scan on your entire repository. Tools like `git-secrets`, Gitleaks, or Trufflehog are free and take about five minutes to run. If anything surfaces, rotate the credential immediately — don't just delete it from the code — and then clean the git history using a tool like `git filter-repo` or BFG Repo Cleaner.
- Run Gitleaks or Trufflehog across your full git history, not just the current files
- Move all secrets into environment variables (`.env` locally, platform secrets in production)
- Confirm your `.env` file is in `.gitignore` — check this explicitly, don't assume
- Rotate any credential that was ever committed, even briefly
- Verify your production environment variables are set in Vercel, Railway, Render, or wherever you're deploying
2. Authentication and Authorisation: Two Different Problems
Authentication is proving who you are. Authorisation is proving you're allowed to do what you're trying to do. Vibe coded apps often get authentication roughly right — especially if they're using Clerk, Supabase Auth, or NextAuth, which handle the hard parts — but they frequently skip authorisation checks.
The classic failure mode: you're logged in as User A, and you can access User B's data just by changing an ID in the URL or API request. If your app has records tied to users — orders, profiles, documents, anything — you need to verify on every data fetch that the requesting user actually owns or has access to that record. AI tools often scaffold the happy path (fetch this record by ID) without adding the ownership check.
Go through every API route or server action in your app that reads or writes user data. For each one, ask: does this check that the authenticated user has permission to touch this specific record? If the answer is "I'm not sure," treat it as a no until you verify.
Quick test to run right now
Create two test accounts in your app. Log in as account 1, find a record ID (an order, a document, a profile). Log out and log in as account 2. Manually construct the URL or API call to fetch that record using account 2's session. If it returns data, you have a broken access control vulnerability — one of the most common and most impactful security issues in web apps.
3. Database Security: Row-Level Access and Direct Exposure
If you're using Supabase (which many vibe coded apps do, since it's quick to set up), there's a specific thing to check: Row Level Security (RLS). By default, Supabase tables have RLS disabled, which means any authenticated user can read and write any row in any table. If you're using the Supabase client directly from the frontend without a backend API layer, this is a critical issue.
Enable RLS on every table that holds user data, then write policies that restrict access to the owning user. Supabase's documentation on RLS is genuinely good, and AI tools can help you write the policies once you understand the pattern. But you have to turn this on manually — it doesn't happen automatically.
More broadly, make sure your database is not directly exposed to the public internet. Connection strings with credentials should live in environment variables on your server, never in client-side code. If you're using a hosted database (PlanetScale, Neon, Supabase, Railway), verify that connection access is restricted to your application's IP range or uses a connection pooler with proper authentication.
4. Input Validation: Trusting User Data You Shouldn't
Any data that comes from a user — form fields, URL parameters, file uploads, API payloads — needs to be validated and sanitised before your app acts on it. AI-generated code often skips or under-implements this. The risks range from broken functionality (a user enters unexpected input and crashes a process) to more serious issues like SQL injection or cross-site scripting.
For most modern JavaScript/TypeScript apps, Zod is the practical answer. It lets you define a schema for what you expect, and it validates and parses incoming data against that schema. If you're using tRPC or a similar framework, schema validation is often built in. The key is to validate at the boundary — at the API route or server action — not just on the frontend form.
- Every API route that accepts POST/PUT/PATCH data should validate the request body against a schema
- File uploads should check type, size, and (if storing) scan for malicious content
- URL parameters used in database queries should be validated and never interpolated directly into raw SQL strings
- Error messages returned to users should not expose internal system details (stack traces, database schema names, etc.)
5. Dependencies: The Invisible Attack Surface
When an AI tool scaffolds your project, it installs a set of npm (or pip, or gem) packages. Those packages have their own dependencies. The full dependency tree of a vibe coded app is often hundreds of packages, and you've probably never looked at most of them. Some of those packages have known vulnerabilities.
Run `npm audit` (or the equivalent for your package manager) before launch. This checks your installed packages against a database of known vulnerabilities and tells you which ones are critical, high, moderate, or low severity. Fix or replace any critical or high-severity findings. For lower-severity issues, assess whether the vulnerable code path is actually reachable in your app.
Also check for packages that are unmaintained, have unusual permissions, or were added without a clear reason. AI tools sometimes add packages to solve a specific sub-problem and don't remove them when the approach changes. A leaner dependency tree is a more secure one.
6. Configuration and Deployment: The Last Mile
A few things to verify before your app goes live that are easy to miss in the scramble to launch:
- HTTPS is enforced. Your hosting platform (Vercel, Netlify, Railway) typically handles this, but verify that HTTP requests are redirected to HTTPS, not just served over both.
- CORS is configured correctly. If your app has a separate API and frontend, the API's allowed origins list should specify your domain explicitly, not be open with a wildcard (`*`) in production.
- Error handling doesn't leak internals. Uncaught errors shouldn't return stack traces or database details to the client in production. Configure a generic error response for production environments.
- Admin routes are protected. If your app has any admin functionality, confirm it requires authentication and that the check happens server-side, not just via a hidden URL.
- Rate limiting is in place on auth endpoints. Without rate limiting, login and signup endpoints are vulnerable to brute-force attacks and credential stuffing. Most hosting platforms let you configure this at the edge.
How to Prioritise If You're Short on Time
If you can only do three things before launch, do these in order: scan for and rotate any exposed secrets, verify your authorisation checks with the two-account test, and enable RLS on your database tables if you're using Supabase. These cover the failure modes most likely to cause real harm quickly.
The remaining items — input validation, dependency auditing, deployment configuration — are important but less likely to result in an immediate breach. Build them into your first post-launch sprint rather than delaying launch indefinitely.
Security isn't a one-time check. As you add features, the surface area grows. The habit of thinking about authorisation checks, validating inputs, and keeping dependencies current is more valuable than any single audit. If you want a structured way to assess where your app stands before launch or before your first enterprise customer signs on, that's exactly the kind of review we do as part of Atlas Atlantic's founder assessment work.
The honest summary
Vibe coded apps are not inherently insecure. They're insecure in predictable ways that are fixable with methodical review. The checklist above covers 80% of the real risk for a typical early-stage app. The remaining 20% depends on what your app actually does — and that's where an experienced eye on your specific codebase earns its keep.
Frequently asked questions
Is AI-generated code less secure than code written by a human developer?
Not necessarily less secure by nature, but insecure in more predictable ways. AI tools optimise for producing working code quickly, not secure code. They commonly skip authorisation checks, mishandle secrets, and use default configurations that aren't production-ready. A careful human developer would catch these in review; with vibe-coded apps, that review step often never happens.
What are the most common vibe coding security risks I should fix before launch?
The three highest-priority risks are: API keys or credentials committed to your git history, missing authorisation checks that let one user access another user's data, and databases (especially Supabase) with Row Level Security disabled. These three categories account for the majority of real security incidents in early-stage vibe-coded products.
How do I check if my vibe-coded app has hardcoded secrets?
Run a tool like Gitleaks or Trufflehog against your full git repository — not just the current files, but the entire commit history. These tools scan for patterns matching API keys, tokens, and passwords. They're free, open source, and can be run in a few minutes. If anything surfaces, rotate the exposed credential immediately before cleaning the history.
Do I need a professional security audit before launching my app?
For a typical early-stage app with a small user base and no sensitive personal or financial data, the checklist in this guide covers the most critical risks. A professional penetration test becomes important when you're handling regulated data (health, financial, legal), have enterprise customers with compliance requirements, or are scaling significantly. Start with the basics yourself, and bring in professional review when the stakes justify it.
What is broken access control and why is it so common in AI-generated apps?
Broken access control means a user can access data or take actions they shouldn't be permitted to. It's common in AI-generated apps because tools like Cursor and Lovable scaffold the happy path — fetch a record by ID — without adding the check that verifies the requesting user owns that record. It's not a subtle bug; it's a missing feature that the AI simply doesn't add unless explicitly prompted.
Does using Supabase Auth mean my app is secure?
Supabase Auth handles authentication well — it verifies who a user is. But authentication alone doesn't make your app secure. You still need to enable Row Level Security on your database tables to control what data each user can access, and you need to add authorisation checks in your application logic to verify users are permitted to take specific actions. These are separate concerns that require separate implementation.
Free · 10 minutes
Build your founder operating system
Answer a short guided assessment about your business model, sales motion, and operations. Download a custom roadmap with concrete next steps you can start this week.
Start the Founder ToolkitKeep reading
Your Vibe-Coded MVP Is Not a Product Yet. Here's the Gap.
Learn how to make a vibe coded app production ready: the 6 gaps founders miss, what breaks first, and how to cross from prototype to durable product.
How We Built GrocerySaver: From Prototype to Real Product
A behind-the-scenes look at how we turned GrocerySaver from a scrappy prototype into a real product Canadians use to save on groceries every week.
Building Permagent: An AI Agent That Outlasts Every Subscription
How we built Permagent, a local-first, open-source AI agent operating system with persistent memory—and what it takes to ship a real AI product, not a demo.