Quick Summary
This article walks through a real vibe coding security review we ran on a client’s AI-generated application before launch. We cover how we audited the codebase, the critical Vibe Coding Security Risks we found, how each flaw traced back to a specific prompt, and the fixes and guardrails we used to get the app production-ready without rebuilding it from scratch.
Introduction
A founder came to us with an app that already worked. It demoed cleanly, early users were signing up, and an investor call was a week out. The whole thing had been built through prompts in Lovable, no in-house engineers involved, and it looked finished. The client did not want a rewrite. They wanted one question answered before launch: is this safe to put real customer data into?
That question is the entire reason vibe coding security matters, and it is the part almost nobody checks until something has already gone wrong.
Here is what we walked in expecting to find, the vibe coding security risks we have learned to look for in any AI-generated codebase:
- Secrets and keys sitting in the frontend bundle
- Database tables that anyone with the public key could read
- Endpoints with no authentication behind them
- No rate limiting on anything that actually mattered
We found all four, and a few more. A 2026 Cloud Security Alliance research note summarizing Veracode’s testing put it bluntly: roughly 45% of AI-generated code samples introduce at least one OWASP. Top 10 vulnerabilities, and that rate has not improved across testing cycles. The speed of vibe coding is real and worth having. The security gap underneath it is just as real, and it never shows up in a demo.
The Client Project: A Vibe-Coded App That Passed the Demo but Not the Audit
The client is an early-stage US SaaS startup. Their product is a booking and scheduling tool aimed at small clinics, the kind of app where a single account holds names, contact details, and appointment history for hundreds of real people.
How it was built: Almost entirely through natural-language prompts in Lovable, over about six weeks. No traditional engineering team, one technical co-founder steering the prompts.
The stack the AI produced: A React frontend with a Supabase backend handling the database, authentication, and file storage. A standard, well-supported setup, which is part of why it looked so trustworthy.
What they wanted from us: Not a feature build. A pre-launch check. Their exact words were close to “tell us if we can turn this on for real customers.”
Here is the trap. The app passed every test the founder knew how to run. Sign-up worked, login worked, the dashboard loaded, and data saved. From the outside, it behaved like a finished product. The problems were all in the places a demo never exercises: what happens when someone sends a request the UI would never send. That gap is the first thing our Lovable developers check for, and it is exactly what a solo founder has no way to catch alone.
How We Ran a Vibe Coding Security Audit on the AI-Generated Codebase
We treat AI-generated code as untrusted by default, the same way we would treat code from a contractor we have never worked with. Our vibe coding security audit on this project ran in four passes, and we did them in this order on purpose.
- Secrets and configuration sweep: We scanned the repo and the built frontend bundle for keys, tokens, and credentials using gitleaks, then opened the production bundle in a browser to see what was actually shipping to the client.
- Static analysis: We ran Semgrep across the codebase to flag injection patterns, unsafe data handling, and missing input validation.
- Dependency and package check: We ran npm audit and cross-checked every package the AI had pulled in, looking for abandoned libraries and anything that did not need to be there.
- Manual review and live probing: This is where the real findings came from. We read the Supabase access policies by hand, mapped every API route, and sent requests the app’s own interface would never send, with no auth token, with another user’s ID, with malformed input.
The automated tools caught maybe a third of what mattered. The rest came from a human asking, “What is actually stopping me from reading someone else’s data here?” and finding that the answer was nothing.
The Critical Vulnerabilities We Found, Ranked by Blast Radius
We logged 14 issues in total. Four were critical, meaning a stranger with no account could reach real user data. Ranked by how much damage each one could do:
- No Row Level Security on the database: This was the big one. Supabase ships a public “anon” key that lives in the frontend by design, and it is safe only if Row Level Security policies restrict what that key can touch. The AI never set those policies. Every table was readable by anyone who pulled the key out of the bundle, which takes about thirty seconds. The entire customer list was effectively public.
- An admin function with no authentication check: A serverless function that returned account-wide data had no verification of who was calling it. The UI only showed it to admins, so in testing, it looked fine. The endpoint itself did not care who you were.
- A live third-party API key in the frontend: Beyond the expected Supabase key, the AI had hardcoded a payment provider’s secret key directly into client-side code during one iteration. Anyone reading the bundle could have run charges on the client’s account.
- An unparameterized query in an edge function: User input was being concatenated straight into a query string, the classic injection opening that lets an attacker rewrite what the query actually does.
That is the headline list, but most of the issues sat in the medium-risk findings, and they matter more than they look because attackers chain them together. The ones we flagged:
- A public storage bucket: Uploaded files, including documents tied to specific accounts, were reachable by direct URL with no permission check.
- A wildcard CORS policy: The backend accepted requests from any origin, which removes one of the few browser-level protections standing between the app and a malicious site.
- No rate limiting on login, OTP, or password reset: Nothing stopped an attacker from running thousands of guesses a minute, which turns a weak password into an open door.
- Account enumeration on password reset: The endpoint responded differently for real and fake email addresses, handing an attacker a way to confirm who has an account before targeting them.
- Session tokens that never expired: A token stolen once stayed valid indefinitely, so a single leak became permanent access.
- Verbose error messages: Failed requests returned database structure and stack traces, which is a free map of the system for anyone probing it.
- Two abandoned packages: Dependencies the AI pulled in during one prompt and never used, both unmaintained, both adding attack surface for nothing.
None of this was unique to our client. We see the same vibe coding security risks on nearly every AI-built app that lands on our desk: tables left open, secrets in the bundle, endpoints with nothing guarding them. The tools differ, and the founders differ, but the missing safeguards are almost always the same ones.
How We Traced Every Vulnerability Back to the Prompt That Caused It
This is the part most security write-ups skip, and it is the most useful thing we did. We asked the founder for the prompt history and traced each flaw back to the instruction that created it. The pattern that emerged explains the whole problem.
| The prompt
| What the AI did
| The hole it left
|
|---|
| "Build a dashboard that shows the user's bookings."
| Wired the frontend straight to the database tables
| No access rules, every row reachable
|
| "Make the admin page load all accounts."
| Created a function that returns everything
| No check on who is calling it
|
| "Connect Stripe so users can pay."
| Pasted the secret key where it was easiest, the frontend
| Live key exposed in the bundle
|
| "Make the dashboard load faster."
| Regenerated the component without the earlier auth guard
| Authentication silently removed
|
That last row is the one worth sitting with. An early prompt had actually added an authentication check. A later, totally reasonable prompt about performance caused the AI to rewrite that component from scratch, and the new version quietly dropped the auth guard. Nobody asked it to. Nobody noticed, because the screen still looked the same.
Our lead reviewer kept coming back to this: the model is not trying to be insecure, it is trying to satisfy the last thing you asked for, and it has no memory of why the safe version was safe. It optimizes for “this works and looks right,” not “this holds up when someone attacks it.” It has never been on the receiving end of a breach, so it has none of the defensive instinct an experienced engineer carries by default.
That is the real vibe coding security lesson here. The flaws were not random. Each one was a logical, literal response to a prompt that did not mention security, because almost no prompt does. And the regression problem means a clean codebase does not stay clean. The Georgia Tech Vibe Security Radar has tracked exactly this trend at scale, with AI-attributable vulnerabilities climbing sharply through early 2026 as more code gets generated this way.
How We Secured the App Without Rebuilding It From Scratch
The founder’s worst fear was that we would tell them to start over. We did not, and that was the right call. Rebuilding only makes sense when the architecture itself is broken. Here, the structure was sound, the schema was reasonable, and the UI was genuinely good. The problems were missing safeguards, not a rotten foundation. So we fixed it in place. That call, fix or rebuild, is the first thing we settle on any cleanup, and it shapes how we scope our vibe coding services, because getting it wrong burns weeks in either direction.
What we kept: The React frontend, the database schema, the overall app structure, and most of the working features.
What we rewrote:
- Wrote proper Row Level Security policies so every table check passes through the logged-in user’s identity
- Added real authentication and authorization checks to every function, not just the UI
- Moved the payment key and all secrets server-side, out of the bundle, into environment variables
- Parameterized the vulnerable query and added input validation across endpoints
- Locked CORS down to the actual domains, killed the wildcard
- Added rate limiting to login, OTP, and password reset
Then we did the part that catches what fixes break. Vibe coding security is not a one-time scan, so we ran the whole probing pass again, plus a focused round of QA for vibe coded app behavior: testing what happens with the wrong token, another user’s ID, and bad input, on every route, not just the ones the interface uses. A fix that closes one hole and opens another is common, and the only way to know is to attack the app again after patching.
Worried Your AI-Built App Is Hiding the Same Flaws?
Hire vibe coding cleanup specialists from Bacancy to audit your AI-generated codebase, fix what is exposed, and re-test it properly before real users and real data ever touch it.
How We Built Vibe Coding Security Into the Client's Prompt and QA Process
Patching the app was half the job. If the team kept prompting the same way, they would reintroduce the same classes of flaws in the next sprint. So we left three things behind.
- A security rules file the AI reads automatically: A short document in the project root that tells the AI tool, on every generation, to enforce access rules, never put secrets in the frontend, validate input, and keep authentication checks intact when refactoring. It turns the missing requirements into standing instructions.
- A pre-merge review checklist: A focused list aimed squarely at the AI failure patterns: secrets in the bundle, access rules on new tables, auth on new endpoints, CORS, rate limits. Five minutes per change.
- A QA pass built for AI output: Standard testing checks that features work. QA for vibe-coded app builds has to also check that the safe behavior survived the last round of prompting, because that is exactly what AI tends to undo quietly.
“The mistake teams make is trusting that because the AI wrote it correctly once, it will stay correct. It will not. Every prompt that touches a file can rewrite the safe parts without telling you. You have to test for that on purpose, every time, or you are shipping blind.” Karmrajsinh Vaghela, Senior Technical Project Manager, Bacancy Technology
The founder’s team now treats the AI like a fast junior developer whose work always gets reviewed. That single shift does more for their long-term security than any one fix we shipped.
What to Settle Before You Ship a Vibe-Coded Product
The app went live a week later. Same product, same speed advantage that got it built in six weeks, minus the four critical holes that would have leaked customer data on day one. The founder’s instinct to ask before launching is the thing that saved them.
There is one takeaway: a vibe-coded app is safe to ship when someone has actually tried to break it, not when it demos well. Vibe coding security is not the enemy of speed. It is the small, deliberate step that keeps the speed from costing you everything later. The economics only work when you treat the AI as a tool that needs direction and review, not a replacement for both.
If you are building this way and want it done with the safeguards baked in from the first prompt, hire vibe coding developers from Bacancy who know where the AI cuts corners and how to stop it before it reaches production.