Vibe coding made building so fast that the new risk is shipping something you never actually read. That is fine for a throwaway prototype. It stops being fine the moment a real person types real data into your app, because the code you did not read is, on average, not secure.
The hard number comes from Veracode's 2025 GenAI Code Security Report, which tested code generated by more than 100 large language models against the OWASP Top 10. It found that 45 percent of the generated samples introduced a known vulnerability. The detail that should change how you work: the models got better at writing code that runs, but they did not get better at writing code that is safe. Security performance was flat regardless of model size. A smarter model does not save you here.
This is not a "vibe coding is bad" article. It is the opposite. The speed is real and worth keeping. You just have to add back the one filter that the old slow way of building used to give you for free: somebody understanding the code before it went live. OWASP now tracks this exact failure under the candidate label "inappropriate trust in AI-generated code", which is a polite way of saying we ship things nobody checked. The checklist below is that check, compressed into an afternoon and written for makers, not security engineers.
Why this matters more for vibe-coded apps specifically
Two things stack up. First, the generation rate of flaws is high, per the Veracode data above. Second, the people shipping vibe-coded apps are, by definition, often not the people who would spot the flaw. That combination is why the public failures have been so blunt.
You can watch it happen in real time on the maker forums. A widely shared r/webdev thread from March 2026 documented a live app that left its Stripe API keys public in the front end. In February 2026 a vibe-coded project drew enough scrutiny that, per a widely-followed thread, the creator took the whole thing private and deleted their accounts after a security flaw was exposed publicly. None of these makers set out to be careless. They shipped code they had not read, on a platform that defaulted to insecure, and the internet found it within hours.
The good news in all of that: the failures repeat. Almost every one is a variation of "a secret got out" or "the data had no lock on it." That makes them checkable. Here is the list.
1. No secrets in the browser
This is the one that bites first and bites hardest. AI assistants hardcode credentials constantly, because their training data is full of code that does exactly that. The fix is a five-minute check anyone can run.
Deploy your app, open it, and view source. In the browser dev tools, open the Network or Sources tab and search the loaded JavaScript for these strings:
sk_andsk_live(Stripe secret keys)service_role(Supabase admin key)AKIA(AWS access key IDs)secret,password,token, and the names of any services you use (OpenAI, Anthropic, your email provider)
Anything sensitive that loads in the browser is readable by every single visitor, forever. There is no hiding it; minification is not protection. If you find a secret in the client, you have two jobs: move that call to a server-side function so the key never reaches the browser, and rotate the key, because you must assume it is already leaked. A key that was ever public is a dead key.
Then catch the ones hiding in your git history. Run a free scanner like gitleaks over your repository. A secret committed three weeks ago and "deleted" since is still sitting in the history for anyone who clones the repo. Rotate anything it flags.
2. The right key on the right side
Most vibe-coded apps that use a hosted database use one with two kinds of keys: a public one that is meant to be seen, and an admin one that is not. The single most common catastrophic mistake is putting the admin key where the public one belongs.
The clearest example is Supabase, the default backend behind a lot of AI app builders. Per the Supabase documentation, the anon key is public by design and safe to ship to the browser, because access is supposed to be controlled by database policies rather than by hiding the key. The service_role key is the opposite: it bypasses every access policy and grants full read and write to your entire database. It belongs only in server-side code, never in anything the browser downloads. If your view-source check in step one turned up service_role, that is not a minor issue, that is the whole database exposed.
The rule generalizes beyond Supabase: every service has a publishable key and a secret key, and the secret one stays on the server. If you are not sure which is which, your provider's docs say so explicitly. Read that one page.
3. A real authorization layer on your data
This is the subtle one, and it is the one that produced the most-cited vibe-coding breach to date. Having a public key in the browser is fine. Having a public key in the browser and no rules on what that key can touch is a disaster.
In May 2025, CVE-2025-48757 documented that more than 170 Lovable-generated projects had Supabase tables that anyone could read using just the public anon key, because the generated code never enabled Row Level Security. With no policy on a table, the auto-generated REST API treats it as open: an attacker swaps the query and dumps your full user list, payment records, or stored credentials, without ever logging in. The fix per table is one line of SQL, ALTER TABLE your_table ENABLE ROW LEVEL SECURITY;, followed by writing a policy that says who is allowed to see what.
So the check is: for every table or collection in your app, can a logged-out stranger read it? Can they write to it? The answer for anything containing user data should be no, enforced at the database, not just hidden by your UI. A page that "does not show" the admin data is not security; if the data is one API call away, it is public. This is the same shift from forms to state that we cover in when to graduate from no-code: the moment you hold other people's data, you need a backend that enforces who touches it, which is also the argument for picking a real data layer over a spreadsheet.
4. Validate everything that comes from a user
The Veracode study found that injection-style flaws dominate AI-generated vulnerabilities, and that the models were especially weak at defending against cross-site scripting, failing to do so in the large majority of relevant samples. In plain terms: AI-generated code tends to trust input that it should not.
You do not need to become a security researcher to cover the common cases:
- Database queries. Make sure user input is passed as parameters, not glued into a query string. If your code builds SQL by concatenating strings with user input in them, that is a SQL injection waiting to happen. Ask your AI assistant to rewrite it with parameterized queries, then confirm it actually did.
- Anything you render back to the page. If a user can type something that later shows up on a page (a name, a comment, a profile bio), it must be escaped so a
<script>tag is shown as text, not run as code. Most modern frameworks do this by default; the danger is the one place your generated code reached for a raw-HTML insert to "make it work." - File uploads and redirects. Limit upload types and sizes, and never redirect a user to a URL they fully control. Both are favorite footguns in generated code.
A fast way to surface these without reading every line: paste a file into a fresh chat and ask the model to "list every place untrusted user input reaches a database query, the page, the filesystem, or a redirect, and whether it is validated." It is much better at finding these when you ask it to look than it is at avoiding them while building.
5. Check your dependencies
AI assistants reach for whatever package was popular in their training window, which is sometimes outdated and occasionally a package with a known vulnerability. They have also been observed inventing package names that do not exist, which attackers then register and fill with malware, a tactic called slopsquatting. So two passes:
- Run your package manager's audit (
npm audit,pip-audit, or your platform's built-in equivalent) and resolve anything rated high or critical. - Glance at the dependency list and confirm each package is real and widely used. A package with almost no downloads that you do not remember asking for is worth a hard look before it ships.
This step takes five minutes and closes off the supply-chain end of the problem, which is the part you cannot fix by reading your own code.
The afternoon, in order
- View source, hunt for secrets. Grep the loaded JavaScript for keys; run gitleaks over the repo. Rotate anything exposed.
- Sort your keys. Confirm only publishable keys are in the browser and every secret/admin key is server-side only.
- Lock the data. For every table, prove a logged-out stranger cannot read or write user data. Enable Row Level Security and write the policies.
- Validate input. Parameterized queries, escaped output, constrained uploads and redirects.
- Audit dependencies. Run the audit, resolve highs and criticals, sanity-check the package list.
That is the whole list. It is not a replacement for a real audit on a funded product handling sensitive data, and if you are in a regulated space the bar is higher; see the HIPAA checklist for solo makers and EU data residency for no-code apps for what changes there. But for a side project going live to its first real users, these five passes catch the failures that actually make the headlines.
The mindset, not just the checklist
One senior engineer's much-shared r/ClaudeAI post described happily vibe coding all of their side projects from a phone, without reading the code, by following a set of rules. The key one is the one that matters here: the rules exist precisely because they do not read every line. Guardrails replace review. You can ship at vibe-coding speed and still be safe, but only if you bake the checks into your launch process instead of trusting that the model got it right.
Treat AI-generated code the way you would treat code from a fast, talented contractor you have never met: useful, worth keeping, and never shipped to production without someone running the checklist first. That someone is you, and it is an afternoon, not a career change.
Build fast. Launch checked. The order is the whole game.