Next-Gen App & Browser Testing Cloud
Trusted by 2 Mn+ QAs & Devs to accelerate their release cycles

Vibe coding risks measured on six live apps: five logged errors on load, two lost state on reload, one answered from an empty form. Plus what test catches each.

Anubhav Singhmaar
Author

Himanshu Sheth
Reviewer
Published on: August 31, 2026
Overview
Vibe coding risks are the defects that survive when an AI writes the code and nobody verifies the behavior. We tested six live vibe-coded apps in a real browser: five logged an error on first load, two silently lost state on reload, and one returned a confident financial verdict from an entirely empty form.
Failure modes we observed directly
What catches defects a green build misses
Checks that run the application rather than read it. Fail the run on console and network errors, assert response status, submit every form empty, and reload mid-flow. We ran this probe on TestMu AI Browser Cloud in real Chrome sessions, and four checks were enough to surface defects in five of six apps.
In Stack Overflow's 2025 Developer Survey, the single biggest frustration developers report with AI tools, cited by 66%, is solutions that are almost right but not quite. A further 45.2% say debugging AI-generated code takes longer than debugging their own.
Almost right is the hardest defect class to test for. It compiles, it renders, and it fails in a way nobody wrote an assertion against.
So we stopped reading about it and went looking. We ran a fixed six-check probe against six live applications built with Bolt, Lovable, and Base44, in real Chrome sessions, and recorded what broke. This article is that data, the nine failure modes it maps to, and an honest account of which test type catches each one.
Vibe coding risks are the defects that reach production when an AI generates the implementation and no human verifies the resulting behavior. The phrase covers the same ground as vibe coding quality issues and problems with vibe coding, and it spans four categories: correctness, security, maintainability, and the review capacity to catch any of them.
The distinguishing feature is not that generated code is sloppy. It is that generated code is fluent.
Veracode's Spring 2026 GenAI Code Security Update reports that syntax correctness now exceeds 95%, while the security pass rate has stayed essentially flat at around 55% since 2023. The surface got polished while what sits underneath did not move.
That gap is what breaks conventional quality signals. A linter, a compiler, and a type checker all read the same closed surface the model wrote against, so they agree with it.
If you want to know whether the software is right, something has to run it. That is the argument behind continuous verification for AI-generated code, and it is what our probe was built to test.
We tested six live vibe-coded web applications on TestMu AI Browser Cloud, in real Chrome sessions driven by Playwright, on 27 August 2026 under build 102694693. Six is a small sample and we are not going to present it as a survey. Read every number here as "in these six apps", never as "in vibe-coded apps".
Every target had to be attributable. We accepted an app only when the builder was provable from the deploy domain, an intact platform badge in the rendered DOM, or a hackathon gallery entry naming the tool. Four are Bolt projects, one is Lovable, and one is Base44.
We rejected roughly twenty-five other candidates, most of them because they looked like someone's live business rather than a demo.
Each app got the same six checks, in the same order, with a twenty-second per-check timeout:
Getting thirty-six trustworthy results took twenty-one browser sessions. Two operators ran the probe independently and both discarded their early passes, because seven distinct defects in our own harness had produced false verdicts about the apps rather than real findings. The most instructive was a loose call-to-action matcher that clicked a colour swatch named "Indigo" and then reported a dead control.
Five of six apps logged an error before anyone touched them. No app failed the primary-control check, so nothing in the sample was broken in the obvious way. Every failure we found was the quiet kind.
| Check | Result | What we saw |
|---|---|---|
| Load | 5 of 6 failed | All four Bolt apps request a favicon left over from the unmodified Vite starter and get a 404. One app hit a 502 on a dead badge host, and one returned 401 on an authenticated endpoint. |
| Primary control | 6 of 6 passed | No dead controls. On one Bolt app the main call to action is disabled until a URL is entered, so we exercised the next-ranked control; on another the click produced a file download rather than a change of view. |
| Empty submit | 1 clear failure, 3 partial | One app accepted an empty form and produced a confident result. Three blocked the submit only by disabling the button, with no message. |
| Hostile string | 4 of 6 exercised | No client-side HTML injection in any app that could receive the string. One app has no free-text field; on another, Chrome's own number input rejected every character. |
| Reload | 2 of 6 failed | Two apps discarded in-progress state and dropped the user back to the start with no warning. |
| Deep link | 1 of 6 failed | One app rendered a correct "Page Not Found" screen while returning HTTP 200. The rest inherited a real 404 from their host. |
The single most useful frame in the study came from the empty-submit check on a Bolt-built financial runway calculator. With both inputs blank, it reports a runway of "Indefinite" under a green tick, labels it "Excellent financial runway", and offers to export a summary of a model containing no data.

Nothing about that screen is broken in a way software can detect. The layout is clean, the arithmetic is internally consistent, and a visual-regression baseline captured from this exact state would pass it forever. It is wrong only if you know what the answer is supposed to be.
Six of these we observed directly. Three are invisible from a browser and rest on published research, which we flag explicitly rather than implying our probe found them.
Plausible, well-formed, wrong. The runway calculator above is this class in the wild, and it is the one developers already name as their dominant cost. A generator optimises for output that looks like a correct answer, and a confidently wrong answer satisfies that objective perfectly.
It is also the hardest class to write a test for, because catching it requires knowing the right answer independently of the code that produced it.
Two apps threw away in-progress work when the page refreshed. A quiz discarded the entered name and dropped the user out of a started attempt back to the quiz picker; a game discarded the entered name and the round in progress and returned to its setup screen.
Neither warned, and both rendered a perfectly healthy screen afterwards. It was just the wrong screen.

Generated test suites miss this class specifically, because a model writes the flow the feature describes and no feature description mentions refreshing the page.
One app rendered a correct "404 Page Not Found" view and returned HTTP 200 with it. The screen tells the truth and the response does not. We confirmed the status outside the browser with curl.
A status code is not a pixel and it is not rendered text, so both visual testing and any assertion reading the DOM walk straight past it. The cost shows up weeks later as junk routes in the search index.
All four Bolt apps in our sample request a favicon that ships with the default Vite starter and never existed in the deployed build. Each one 404s on every page load, in production, on a live URL. We reproduced it with curl outside the browser.
With four apps this is a pattern in our sample, not a measured property of any builder, and we are not going to claim otherwise. A related variant: one app embeds a badge image from an external host that returned HTTP 502 during our run and, when we rechecked before publishing, no longer resolved at all. A build that depends on an external asset host inherits that host's lifetime.
One app calls a current-user endpoint on every load of a page that requires no login, and takes a 401 back each time. The app renders correctly and the feature works, so the only visible trace is in the network panel.
Treat it as an auth-boundary smell rather than console noise. On a generated app this pattern usually arrives in platform scaffolding rather than in anything the builder typed, which is exactly why it survives: nobody chose that call, so nobody reviews it.
We did not observe this class, and a black-box browser probe structurally cannot. Our finding that no app rendered injected HTML is a narrow statement about one input path, not a security clearance. This section rests entirely on published research.
That flat security pass rate is an average, and it hides a wide spread. Veracode's Spring 2026 update breaks it down by vulnerability class:
A benchmark of 186 real-world feature requests accepted to ICML 2026 found 57% of agent solutions functionally correct and 11.8% secure, and reports that adding vulnerability hints to the request did not close the gap.
In the field, Georgia Tech's Vibe Security Radar has traced 74 confirmed CVEs to AI-authored commits, 14 of them critical, with command injection, authentication bypass, and server-side request forgery the recurring classes. Their count rose sharply into 2026, though the tool's own coverage expanded over the same period, so that curve is not a clean like-for-like rate.
Also invisible from a browser, since we never saw a manifest. A USENIX Security 2025 study found 19.7% of 2.23 million package recommendations pointed at packages that do not exist, and that 43% of hallucinated names recurred across all ten repetitions of the same prompt.
A 2026 replication across five frontier models puts the rate between 4.62% and 6.10% across 199,845 paired prompts.
That replication is a single-author preprint rather than peer-reviewed research, so weigh it accordingly. The gap between the two figures still matters, because the 2024-era rate is widely quoted as current. Repeatability is the part that has not improved: a name a model invents consistently is a name an attacker can register in advance.
Nothing in the test pyramid catches this one, because it is not a behavior. The code works. In a peer-reviewed MSR 2026 study of AI-generated pull requests, agents produced an Average Max Redundancy of 0.2867 against 0.1532 for humans, and removed fewer lines per pull request than human contributors did, a difference significant at p<0.001.
A larger in-the-wild study of more than 302,000 AI-authored commits across 6,299 repositories, currently an unreviewed preprint, found code smells account for 89.3% of all issues introduced, that more than 15% of commits from every assistant studied carry at least one issue, and that 22.7% of those issues still survive at the repository's latest version.
Read together, those two results describe agents that add without refactoring. The bill arrives at change time, which is why this class costs you nothing on the day it ships.
Naming the risks is the easy half. The operational question is which check actually fires, and the honest answer is that several of these classes are caught by nothing in the functional testing pyramid. Those rows matter more than the ones full of green.
| Failure class | Unit | E2E | Visual | What actually catches it |
|---|---|---|---|---|
| Confidently wrong output | Partly | Partly | No | Only an expectation derived from the domain rather than from the implementation. An expectation generated from the code locks the bug in and then guards it. |
| Validation as a disabled button | No | Only if asserted | No | An accessibility audit, which looks for a status message and a programmatically associated error, or one human trying to use it. An E2E test catches it only if it asserts that a message appeared; the usual assertion is that nothing was submitted, and that passes. |
| State loss on reload | No | Partly | No | An explicitly authored reload step. Generated suites almost never include one, because refreshing is not part of any feature description. |
| Soft 404 | No | Partly | No | An assertion on response status, or an SEO crawler. Reading the rendered text passes. |
| Shipped scaffolding, dead assets | No | Partly | Partly | Failing the run on console and network errors, plus a build-time asset check. Visual diff catches only the variants that render inside the viewport. |
| Authenticated call on anonymous path | Partly | Yes | No | Any run that fails on a 4xx, and a contract pinning who may call the endpoint. Invisible to anything asserting on the DOM. |
| Security vulnerabilities | No | No | No | Static and dynamic analysis, secret scanning, and human security review. A unit test asserts the function does what its author intended, and the vulnerability is what the author intended. |
| Hallucinated dependencies | No | No | No | Install-time dependency scanning and lockfile review. If the package resolves every test passes; if it does not, the build dies before any test runs. |
| Maintainability debt | No | No | No | Static analysis, linting, and code review. A green suite is compatible with any amount of duplication. |
Four of nine rows have no automated functional coverage at all. That is the finding to take away, and it is why "we have tests" is not an answer to "is this vibe-coded app safe to ship".
A pipeline reads what the model wrote using tools that operate on the same closed surface the model was optimising against. Compilers, linters, and type checkers all confirm the code is well-formed, which was never in doubt.
Human review is the intended backstop, and it is the part that scales worst.
Enterprise telemetry from Apiiro, published via the Cloud Security Alliance, reports privilege escalation paths up 322% and architectural design flaws up 153% as AI-assisted development scaled, alongside monthly security findings rising from roughly 1,000 to more than 10,000 in six months. The same source reports those developers committing three to four times as much code.
Both numbers deserve care. A tenfold rise in findings against a three-to-fourfold rise in output means volume explains part of the surge and not all of it, and this is vendor telemetry rather than independent research. What it does establish is that the reviewing has to keep pace with the committing.
DORA's 2025 research puts numbers on the resulting posture: 90% of technology professionals now use AI at work while 30% report little or no trust in the code it produces, and higher adoption is associated with a rise in both delivery throughput and delivery instability.
Speed and breakage rise together because generation got cheaper and verification did not.
Agents write competent test code. The weakness is where the expectation comes from. A test derived from the implementation encodes whatever the implementation does, including its mistakes, and then defends them against future change.
Our runway calculator makes the point concrete. An agent asked to test that app would reasonably assert that submitting the form displays a runway figure. It does, the assertion passes, and the number is meaningless.
We looked at this failure mode in more depth in whether coding agents can test their own code.
The practical safeguard is to keep at least one expectation that the implementation cannot influence. Derive it from the ticket, the specification, or a known-correct value computed by hand, so the check is able to disagree with the code it is checking.
Note: Verification only counts when something executes the application and returns evidence a reviewer can open. Kane CLI does that from the terminal and from CI: you describe the outcome in plain language, it drives a real Chrome browser, and it returns a pass or fail anchored to observed DOM state, network responses, console logs, and screenshots rather than to the source. Start verifying with TestMu AI free.
Everything our probe found is reachable without reading a line of source. Run these four checks first, because they need no knowledge of the codebase and they surfaced defects in five of our six apps.
A Playwright probe for the first two is about a dozen lines, and it is the cheapest gate you can put in front of generated code:
import { test, expect } from '@playwright/test';
const ORIGIN = 'https://www.testmuai.com';
test('loads without errors', async ({ page }) => {
const problems = [];
// Register listeners before navigating, or anything that fails during load is missed.
page.on('console', m => m.type() === 'error' && problems.push('console: ' + m.text()));
page.on('pageerror', e => problems.push('pageerror: ' + e.message));
page.on('requestfailed', r => {
const reason = (r.failure() || {}).errorText || '';
// ERR_ABORTED is normal (prefetch, cancelled navigation). A dead host shows up
// here as ERR_NAME_NOT_RESOLVED, which is the case worth failing on.
if (reason !== 'net::ERR_ABORTED') problems.push(reason + ' ' + r.url());
});
page.on('response', r => r.status() >= 400 && problems.push(r.status() + ' ' + r.url()));
// networkidle is deliberate here: the point is to let every request settle so the
// listeners above see it. Prefer web-first assertions for ordinary functional tests.
await page.goto(ORIGIN + '/selenium-playground/', { waitUntil: 'networkidle' });
expect(problems, problems.join('\n')).toHaveLength(0);
});
// A separate test, so the deliberate 404 below never lands in the list above.
test('a route that does not exist returns 404', async ({ page }) => {
const res = await page.goto(ORIGIN + '/selenium-playground/no-such-route-12345/');
expect(res, 'navigation produced no response').not.toBeNull();
expect(res.status()).toBe(404);
});Expect the first run against your own app to surface noise alongside real defects. Triage it once: move the errors you have consciously accepted into an allowlist, and leave everything else failing. In our sample that would have been one entry for the starter favicon, and the 401 and the dead-host failure would both still have stopped the build.
Point it at your own deployment, run it on every merge, and widen the net from there. Once it passes locally, the same spec runs unchanged across browser and OS combinations on the TestMu AI test automation cloud, which is where the layout and rendering defects our single-browser probe could not see start to show up.
Provenance on this topic is unusually bad. Several widely repeated figures failed verification when we went looking for a primary source, and we excluded them rather than pass them along.
The sample is six apps and the builder mix is uneven, with four Bolt projects, one Lovable, and one Base44. There is no Replit or v0 app in the run, and nothing here supports a per-builder ranking.
One inference deserves naming plainly. Almost every study cited here measures AI-assisted development inside a review process: merged commits, pull requests that reached human reviewers, models scored on controlled tasks, professional developers surveyed about their working practice. None of them measures what someone ships from a prompt with no review at all.
Carrying those rates over to unreviewed vibe-coded output is an inference, not a measurement. It runs in the direction of this article's argument, since reviewed code should be better than unreviewed code rather than worse, but nobody in this evidence set has measured that gap, and neither have we.
Put the console-and-network gate in front of your next generated change today. It is four lines of listener code, it fails loudly, and in our sample it was the single highest-yield check available.
After that, add the reload step and the status assertion, then decide which of the four uncovered rows in the table above you are accepting as risk and which you are going to cover with static analysis, dependency scanning, or review. Writing that decision down is what separates a quality process from an intention. If you want the fuller pipeline, the vibe coding QA workflow lays out which stages actually block a merge, and what vibe coding is covers the ground beneath all of it.
When you want a check that runs the application rather than reads it, TestMu AI's Kane CLI takes a plain-language objective, drives a real Chrome browser, and returns a verdict backed by DOM state, network responses, and screenshots. It runs the same way on a laptop and in a pipeline, and the Kane CLI documentation covers the CI setup.
Author
Anubhav Singhmaar is an AI Product Manager at TestMu AI driving Kane CLI, the command-line tool that brings browser automation to the terminal, turning natural-language flows into runs in a real Chrome browser that return pass or fail with shareable proof. He owns the roadmap and prioritization and works with engineering to ship developer-facing features. Before TestMu AI, he spent over four years at Sprinklr owning enterprise voice AI across APAC and EMEA. A mechanical engineer turned product manager, he grounds guidance in real QA workflows.
Reviewer
Himanshu Sheth is the Director of Marketing (Technical Content) at TestMu AI, with over 8 years of hands-on experience in Selenium, Cypress, and other test automation frameworks. He has authored more than 130 technical blogs for TestMu AI, covering software testing, automation strategy, and CI/CD. At TestMu AI, he leads the technical content efforts across blogs, YouTube, and social media, while closely collaborating with contributors to enhance content quality and product feedback loops. He has done his graduation with a B.E. in Computer Engineering from Mumbai University. Before TestMu AI, Himanshu led engineering teams in embedded software domains at companies like Samsung Research, Motorola, and NXP Semiconductors. He is a core member of DZone and has been a speaker at several unconferences focused on technical writing and software quality.
Did you find this page helpful?
More Related Blogs
TestMu AI forEnterprise
Get access to solutions built on Enterprise
grade security, privacy, & compliance