Skip to main content

Vibe Coding with Confidence: How to Catch the Security Holes AI Leaves Behind

AI-generated code works. That doesn't mean it's safe. Here are the five security holes that show up in vibe-coded apps over and over, and exactly what to ask your AI to catch each one before a stranger does.

Insights
11m read
#VibeCoding#AI#BuildWithAI
Vibe Coding with Confidence: How to Catch the Security Holes AI Leaves Behind - Featured blog post image
Mahmoud Zalt

1:1 Mentor

Are you a software engineer moving into AI?

Let's have a call. I'll help you modernize your skills and learn the tools, systems, and architecture behind real AI products. One session or ongoing.

Writing live

The Vibecoder's Handbook, from idea to production

Everything you need to know about shipping software with AI, from the App idea to production.

What it covers

  • 1PlanStructure your idea into a clear specification
  • 2Dev Set UpPrepare your environment, tools, and AI agent
  • 3AI Set UpSetup your AI agents operating system
  • 4ArchitectLay out a modular codebase for your AI
  • 5BuildImplement the application in working slices
  • 6DebugDiagnose and fix what the agent breaks
  • 7RefineMake it secure, tested, and production-grade
  • 8ShipDeploy to production on real infrastructure
  • 9OperateRun and maintain it in production
  • 10ScaleGrow it to handle real traffic and data
Start Reading Free

77 chapters

v0.1 · 2026 Edition

How do you catch the security holes that AI-generated code tends to leave behind?

You catch them by assuming they are already there and going looking, the way a security-minded engineer reviews a junior developer's first pull request. That means checking five recurring patterns every time you ship: secrets baked into the code, API routes anyone can call without proving who they are, user input that gets trusted instead of checked, database rules that are wide open, and sensitive data stored the easy way instead of the safe way. None of this requires a computer science degree, it requires asking the AI pointed questions, running a couple of free scanners, and testing your own app the way a stranger with bad intentions would. That is what vibe coding with confidence looks like: not avoiding AI-written code, but never shipping it unreviewed.

I'm Mahmoud Zalt, an independent senior AI systems architect. I've been building and shipping production software since 2010, my sixteenth year doing this for a living, and I founded Sista AI (sistava.com), where autonomous AI agents run in production today, not in a slide deck. I've reviewed enough AI-generated codebases to know exactly where they break, and it's almost never the parts that are hard to spot. It's the same five or six things, over and over, hiding in code that otherwise looks fine.

Why AI writes code that works, and still isn't safe

An AI model answering "build me a login form" is solving a narrow problem: produce something that logs a user in. Nobody mentioned an attacker, so the model has no reason to think about one. It will happily generate code that authenticates a real user correctly while leaving a wide-open door for everyone else, because from its point of view, the task is done.

This isn't a fringe problem you'll get lucky and avoid. Veracode's 2025 GenAI Code Security Report tested code from over 100 AI models across 80 coding tasks and found that roughly 45 percent of the samples contained at least one OWASP Top 10 vulnerability when nobody reviewed the output. Cross-site scripting was one of the worst offenders, failing in something like 86 percent of relevant cases. Worse, bigger and newer models were not meaningfully better at this: model size barely moves the needle on security, because security was never what these models were scored on.

So the fix isn't "use a smarter model" or "write better prompts and hope." It's knowing which failure patterns to expect and checking for them every time, whether it's your first vibe-coded weekend project or your fifth.

Pattern 1: secrets hardcoded or shipped straight to the browser

This is the single most common thing I find, and it happens for a boring reason: putting the API key directly in the code is the fastest way to make the demo work right now, and that's exactly what the AI is optimizing for. The key ends up typed straight into a file, in a .env file committed to a public repo, or baked into the JavaScript bundle shipped to every visitor's browser, where anyone can open developer tools and read it in plain text.

The scale is not small. GitGuardian found close to 29 million new secrets exposed in public GitHub commits in 2025 alone, about a third more than the year before, with a meaningful share tracing back to AI-assisted projects. One scan of roughly 5,600 AI-built apps turned up more than 400 exposed secrets. And once a key leaks, it rarely gets cleaned up: researchers retesting older leaked credentials found a majority still valid years later.

How to catch it

  • Ask the AI: "Scan this project for any API keys, tokens, or credentials hardcoded in the source instead of loaded from environment variables, and list every file where you find one."
  • Then ask a sharper question: "Which environment variables used in the frontend code would let someone access data or spend money on my account if copied out of the browser?" A key that reads your database, calls a paid API, or sends email on your behalf does not belong in frontend code, full stop.
  • Run a free scanner before you trust the answer. Gitleaks and TruffleHog both scan a repository's full history in under a minute and catch what a quick read-through misses.
  • Open your deployed site, view the page source and the network tab, and search for anything that looks like a key. If you can see it, so can everyone else.

Pattern 2: API routes nobody is checking the identity of

Ask an AI to "add an endpoint that returns the user's orders" and it usually will, correctly returning orders for whoever is logged in during testing. What it often skips is the part nobody said out loud: reject the request if the caller isn't actually allowed to see those orders. The endpoint works, and it also returns anyone's orders if you swap the ID in the URL, because nothing ever checked whose data was being asked for. That gap has a name, insecure direct object reference, and it's one of the most common bugs in AI-generated backends.

The same blind spot shows up as wide-open CORS settings, where an API accepts requests from any website instead of just your own, because "allow everything" is the fastest way to stop getting blocked while testing. It works in development, and in production it means any site can call your API from a visitor's browser.

How to catch it

  • Ask: "For every API route in this project, tell me whether it checks that the logged-in user owns or is authorized to access the specific resource requested, not just that they're logged in." Logged in and authorized are different checks, and AI code often only does the first.
  • Ask specifically: "Could a logged-in user access another user's data by changing an ID, slug, or filename in a request?"
  • Test it with two accounts. Log in as account A, grab the ID of something belonging to it, log in as account B, and try to fetch that same ID directly. If it works, you've found the hole.
  • Check your CORS configuration for a wildcard origin on any route that touches user data, and ask the AI to restrict it to your actual domain.

Pattern 3: no input validation, so injection walks right in

Every text box in your app is a door. A search bar, a signup form, a comment field, anywhere a person can type something is somewhere an attacker can type something else. AI-generated code tends to trust that input by default: it builds a database query by gluing the user's text straight into the query string, or it renders whatever a user typed directly onto the page for others to see. The first pattern is SQL injection, decades old and still one of the most common issues in freshly AI-written code. The second is stored cross-site scripting, the exact vulnerability the Veracode study found AI models failing to defend against in the large majority of relevant test cases.

Neither requires a sophisticated attacker. SQL injection can be as simple as typing a single quote and a fragment of SQL into a login box. Cross-site scripting can be as simple as pasting a script tag into a comment field and seeing if it runs for someone else.

How to catch it

  • Ask: "Show me every place user input is inserted into a database query, and confirm each one uses parameterized queries or an ORM, not string concatenation."
  • Ask the same for rendering: "Show me every place user-submitted text gets displayed back to other users, and confirm it's escaped so it can't run as HTML or JavaScript."
  • Actually try it. In any form field, type a single quote followed by OR '1'='1, or paste a script tag into a comment field. If either does something unexpected, that field is unprotected.
  • Free scanners like OWASP ZAP crawl a running app and flag both automatically if you'd rather not test every field by hand.

Pattern 4: permissive database rules that hand out everything

If your app uses Supabase, Firebase, or a similar backend, the database itself decides who can read and write what, through row-level security policies or Firestore rules. This is powerful, and it's also exactly the setting an AI will loosen to unblock you the moment a request gets denied during testing. The fastest fix for "my app can't read the data" is a rule that allows anything, and it works, right up until a stranger who was never supposed to see that table opens it directly through the API and reads every row.

This is not hypothetical. A researcher scanned over 1,600 public projects built with a popular AI app builder and found roughly one in ten had inadequate row-level security, exposing more than 300 endpoints, leaking names, emails, phone numbers, addresses, and payment details from databases with no real access control.

How to catch it

  • Ask: "List every table in this database, tell me what row-level security or access rules exist on each, and flag any table where the rule allows unrestricted read or write access."
  • Specifically ask about the pattern that causes most damage: "Are there any rules that just allow access if true, with no actual check on who the user is?"
  • Test it directly. Log out of your app entirely, then use your backend's public API URL to try reading a table with no login. If it returns real rows, your rules aren't doing anything.
  • Double-check that any table you created through raw SQL or an ORM migration, rather than your provider's dashboard, actually has security rules turned on. Some platforms only enable it by default through the visual table editor.

Pattern 5: passwords and sensitive data stored the easy way

Storing a password is a one-line problem an AI can solve several ways, and only one or two are actually safe. The easy way is plain text or a weak, fast hash. The safe way is a slow, purpose-built algorithm like bcrypt or argon2, deliberately expensive to crack even if your database leaks. The same gap shows up with other sensitive fields, ID numbers, payment details, health information, sometimes saved to the database, or even to application logs, with no encryption, because encrypting a field takes an extra step nobody asked for by name.

The good news: this pattern is genuinely easy to check, once you know to ask.

How to catch it

  • Ask: "How are user passwords hashed in this codebase? Confirm it uses bcrypt, argon2, or scrypt, not plain text, MD5, or SHA-256 alone."
  • Ask: "Which fields in this database contain sensitive personal data, and are any stored or logged without encryption?"
  • Wherever possible, don't build authentication from scratch. Use an established provider, Supabase Auth, Clerk, Auth0, instead of asking the AI to hand-roll login and session handling. Fewer custom moving parts, fewer places for this to hide.
  • If you already shipped with a weak hash, plan a migration: rehash passwords the next time each user logs in.

The mental model that catches almost everything else

You don't need a security course to cover the gaps between these five patterns. One question does most of the work: what would a stranger, not a customer, a stranger, try to do to this? Log out and see what you can still reach. Sign up as a second user and see what belongs to the first one you can still touch. Type unexpected input into every field instead of the happy path you tested with. Look at what your app sends back in network requests, not just what it shows on screen, since APIs often return more data than the page displays. Ask this every time you ship a new feature, not just once at the start.

Pair that habit with a short list of free tools: Gitleaks or TruffleHog for secrets, OWASP ZAP for injection and cross-site scripting on a running app, npm audit or pip-audit for vulnerable dependencies, and your backend provider's own security advisor if it has one, Supabase's flags missing row-level security automatically.

None of this replaces judgment. If a scan turns up something you don't fully understand, or your app is about to hold real payment or health data, that's a reasonable point to bring in outside eyes rather than guess, exactly the kind of review I help teams with through AI consulting. For most vibe-coded projects though, the five patterns above and the stranger test get you most of the way to shipping something you can trust.

Frequently Asked Questions

Do I need to know how to code to check for these issues?

No. Every check here is a specific question you ask the AI, a free tool you run, or a simple test you do by hand, like logging out and trying to reach a page you shouldn't be able to. You do need to actually do the checking, though. Reading this and not running any of it protects nothing.

Can I just ask the AI to "make my app secure" and trust the answer?

Not on its own. A vague prompt gets a vague pass, the AI often says things look fine because "secure" wasn't defined narrowly enough to trigger a real check. Ask about one specific pattern at a time, secrets, authorization, unvalidated input, database rules, password storage, and you'll get far more useful answers.

Is it safe to build a real product on Supabase or Firebase?

Yes, both are used in serious production apps. The risk isn't the platform, it's leaving the default or loosened access rules in place, which happens when a rule gets loosened to unblock testing and never tightened back up.

How often should I re-run these checks?

Before your first real launch, and again every time you add a feature touching user data, payments, or a new API route. New holes arrive every time the AI writes new code, so this needs to be a habit, not a one-time audit.

What's the highest-priority thing to check first?

Secrets and authorization. An exposed API key or a missing ownership check can expose your entire user base immediately, with no skill required to find it. Injection and storage issues matter too, but those two are the fastest way for a vibe-coded app to have a very bad day.

Does a more advanced or expensive AI model fix this?

Not meaningfully. Research has found bigger, newer models are about as likely to produce security gaps as smaller ones, because none are optimized for security by default. The fix is the review process, not a better model.

The honest tradeoff

None of this makes vibe coding meaningfully slower. Every check above takes minutes, not days, and most are just a sharper prompt to the same AI that wrote the code in the first place. What it takes is discipline: actually running the checks before you launch, and again after every feature that touches data or money, instead of assuming the AI already thought of it. It usually didn't, not because it's careless, but because nobody asked.

That discipline is the entire difference between vibe coding and vibe coding with confidence. The first ships whatever comes out. The second ships the same code, after making sure a stranger can't quietly walk through the front door. If you want the fuller path, planning, building, hardening, and shipping a product people can trust, I put the whole process in one place, and the first half is free. Read the free handbook ->

Thanks for reading! I hope this was useful. If you have questions or thoughts, feel free to reach out.

Content Creation Process: This article was generated via a semi-automated workflow using AI tools. I prepared the strategic framework, including specific prompts and data sources. From there, the automation system conducted the research, analysis, and writing. The content passed through automated verification steps before being finalized and published without manual intervention.

Mahmoud Zalt

About the Author

I’m Zalt, a technologist with 16+ years of experience, passionate about designing and building AI systems that move us closer to a world where machines handle everything and humans reclaim wonder.

Let's connect if you're working on interesting AI projects, looking for technical advice or want to discuss anything.

Support this content

Share this article

Get notified about new articles

I'll email you when I publish something new. Leave anytime.

Hire AI Employees

Hire AI Employees that work 24/7. No code.

Alice, AI Personal Assistant
AI Assistant

Alice

AI Personal Assistant

Chat Now

CONSULTING

Get AI advisory and consulting.

Architecture, implementation, team guidance.