Vibe Coding Security Risks: Every Vulnerability Found in AI-Built Apps
- Focus
- Vibe Coding
- Risk
- Critical
- Stack
- Supabase/Next.js
- Detection
- Ubserve Runtime Simulation
25 vibe coding security risks ranked by real frequency, from 876 actual Ubserve scans plus documented breaches (Moltbook, Lovable, Base44). Exact fixes for each.
We pulled the real numbers from 876 Ubserve scans. 83.7% of apps ship with a missing security header. 35.7% have no rate limiting. Here's every risk, ranked by how often it actually happens, not how dramatic it sounds.

See what Ubserve finds in your app before you read further.
- ✓60-second scan, no signup
- ✓Built for Cursor, Bolt, Lovable & Supabase
- ✓Exact AI fix prompts for every finding
Vibe coding security risks are documented, consistent, and growing. In 2026 we have real breaches with real numbers. Moltbook shipped with Supabase and no RLS. Three days after launch, 1.5 million API authentication tokens and 35,000 email addresses were exposed. Lovable had a broken object-level authorization flaw sitting open for 48 days. Anyone with a free account could access another user's projects and database credentials in five API calls. Base44 had a critical authentication bypass that would have let unauthenticated users register inside private enterprise applications, responsibly disclosed by Wiz and patched within 24 hours with no confirmed exploitation.
None of these were exotic attacks. They were the predictable output of shipping AI-generated code without a security pass.
This guide ranks 25 vibe coding security risks by how often they actually happen, using real data pulled from 876 Ubserve scans, not by which one sounds most dramatic. Where our own scan volume is too thin to be statistically meaningful (RLS failures and BOLA are rare in raw counts but catastrophic when they occur), we cite the documented industry incidents and research instead of overstating our own sample.
Jump to:
- What is vibe coding security?
- How dangerous is vibe coding?
- Why traditional tools miss vibe coding vulnerabilities
- The 25 vibe coding security risks
- What breaches actually look like
- Platform-level risks (Lovable, Base44, Bolt)
- Pre-deploy security checklist
- Why manual review isn't enough
What Is Vibe Coding Security?
Vibe coding is the practice of building software through natural-language prompts to AI tools (Cursor, Lovable, Bolt, Windsurf, v0), where the developer describes the desired outcome and the AI generates the implementation. Vibe coding security is the discipline of ensuring that what gets generated does not expose user data, credentials, or infrastructure to unintended access.
The distinction that matters: vibe coding generates working code. Vibe coding security ensures the working code does only what the authorized user is allowed to do. Nothing more.
The gap between the two is the gap every documented breach in 2025-2026 fell through. When you prompt Cursor to "add user authentication," it produces code that authenticates users. When you prompt Lovable to "set up the database," it creates tables and connects them. Neither prompt produces the security layer. Authorization checks, row-level policies, key isolation, rate limiting, input validation. These require explicit intention that the prompt never contained.
Vibe coding security is the practice of closing that gap, systematically, before shipping.
How Dangerous Is Vibe Coding?
The data makes the answer clear.
Veracode's 2025 GenAI Code Security Report, which analyzed 80 coding tasks across 100+ LLMs: 45% of AI-generated code samples introduce security vulnerabilities. GitGuardian's State of Secrets Sprawl 2026 found Claude Code-assisted commits carry a 3.2% secret-leak rate, roughly double the 1.5% baseline across all public GitHub commits. Georgetown's Center for Security and Emerging Technology found 86% of AI-generated code samples fail basic XSS defense checks. In March 2026 alone, security researchers tracked 35 new CVEs attributable directly to AI coding tools, up from 15 in February and 6 in January, a near-sixfold increase in two months.
Vibe coding is not inherently dangerous. The tools build fast, and fast code can be made secure. The danger is specific: AI tools optimize for working code. Security is a separate property that working code does not guarantee.
I built my first serious app with Lovable and Supabase. Three months of daily shipping. Every user flow tested and working. I told myself security was a post-launch concern. Then I scanned the deployed app. An API route I had scaffolded in week one had no authentication check. It returned any user's full project data to anyone who knew the URL. I had called it successfully from the frontend dozens of times. I had never once tested what happened when someone called it without a session.
That is the vibe coding security gap. Not broken features. Invisible ones. Every founder I have spoken to who has been breached describes the same pattern. Not code that failed, but code that worked in exactly the wrong direction.
Why Traditional Security Tools Miss Vibe Coding Vulnerabilities
Standard DAST (dynamic application security testing) scanners check your deployed URL for what an external attacker can see: missing security headers, exposed .env files, API keys visible in the JavaScript bundle, CORS misconfigurations. These are real issues. These tools find them reliably.
The vulnerabilities behind every documented vibe coding breach in 2025-2026 are invisible to any URL-based scanner.
You cannot detect a missing auth.uid() in a Supabase RLS policy by scanning a URL. The scanner sees "RLS enabled," which is what you want, but it cannot read the policy logic that determines who the policy actually grants access to. The difference between USING (auth.role() = 'authenticated') (exposes all data to all users) and USING (user_id = auth.uid()) (correctly scopes to the row owner) is invisible from outside the database.
You cannot detect BOLA by scanning a URL. The scanner sees an endpoint that requires authentication: pass. It cannot tell whether the endpoint checks resource ownership after verifying session existence. That requires reading the handler code and verifying the query includes a WHERE user_id = [session.user.id] constraint.
Traditional code review misses these too. For a different reason. The BOLA pattern is invisible to reviewers who only read code as written, because the code works correctly when called with your own resource IDs. Detecting it requires testing with resource IDs that belong to a different user. That is not a code review task. It is an authorization audit.
Wiz Research found that simply adding the word "secure" to an AI coding prompt reduced the average weakness density of generated code by 28.15%, 37.03%, and 42.85% across GPT-3, GPT-3.5, and GPT-4 respectively. Notably, prompts that named specific CWE categories outperformed generic persona-style prompts like "you are a security-aware developer," specificity beats role-play. These are meaningful improvements. They still leave a substantial residual vulnerability rate. Better prompting narrows the gap. Systematic verification closes it.
The 25 Vibe Coding Security Risks, Ranked by Real Frequency
We pulled the real numbers directly from 876 Ubserve scans to answer a simple question: which risks actually happen most, not which ones make the best headline. The first 7 below get full treatment because they're either extremely common or catastrophic when they hit, even at lower raw frequency. The remaining 18 are ranked by how often they actually showed up.
1. API Keys Exposed in Frontend Code
This is the fastest path from launch to a financial incident.
When you prompt any AI tool to add an external service (OpenAI, Stripe, Resend, Twilio), the path of least resistance is a client-side call. The key goes into the JavaScript bundle. The bundle is public. Automated scrapers scan for key patterns within hours of deployment. GitGuardian processes millions of repositories daily and finds exposed secrets less than 24 hours old.
// The most common AI-generated implementation
const response = await openai.chat.completions.create({
model: 'gpt-4o',
messages: [{ role: 'user', content: prompt }],
// process.env.OPENAI_KEY is in your client bundle.
// Every visitor to your site has this key.
});
The NEXT_PUBLIC_ prefix makes it worse. Variables prefixed with NEXT_PUBLIC_ are intentionally baked into the client bundle. AI tools use them because they are the obvious way to share values with the frontend. For a site URL or a public analytics ID, that's correct. For API keys, it's a direct path to credential theft.
Fix: Every call to a paid external service goes through a server function. The key lives in server-only environment variables. The client calls your Next.js API route, your route calls the provider. The key never touches the bundle. See our guide to removing exposed API keys if you have already shipped.
2. Missing or Broken Supabase RLS
Row Level Security is the most misunderstood security control in vibe-coded apps. In raw scan counts it's rare, our own scan history shows it in less than 1% of apps directly, but that number is misleading: most founders fix it immediately after a scan flags it, and the ones who ship without fixing it are exactly the ones who end up in an incident report. This is a case where we cite the documented industry incidents rather than our own thin sample, because the real-world damage from RLS failures is disproportionate to how often our scans happen to catch it mid-build.
The Moltbook breach in January 2026 was pure RLS failure. The app launched, grew quickly, and exposed 1.5 million authentication tokens because the Supabase database had no row-level security configured. The full incident breakdown is in our vibe coding hacks post. Every table was readable by any authenticated user. The product worked perfectly. The security was entirely absent.
Enabling RLS is not enough. An enabled RLS table with a policy that does not correctly reference auth.uid() is still a data leak. It just looks more secure because the setting is on.
-- This policy compiles and passes every happy-path test
CREATE POLICY "users can read their team's data"
ON team_documents FOR SELECT
USING (team_id IN (SELECT team_id FROM memberships));
-- The problem: missing auth.uid() check
-- Any authenticated user can read every team's documents
-- because the subquery is not scoped to the requesting user
-- The correct version
CREATE POLICY "users can read their own team's data"
ON team_documents FOR SELECT
USING (
team_id IN (
SELECT team_id FROM memberships
WHERE user_id = auth.uid() -- scoped to the requesting user
)
);
Fix: Every RLS policy must reference auth.uid(). Every table needs policies for all four operations. SELECT, INSERT, UPDATE, DELETE. Test each policy with a denied-access case from a different user's session. Our Supabase security checklist covers every policy pattern you need before launch.
3. Service Role Key in Client Code
The Supabase service role key bypasses every RLS policy on every table. That is its entire purpose: server-side admin operations that need to work around row-level restrictions. If that key reaches the browser, every visitor to your app has unrestricted admin access to your entire database.
AI tools scaffold Supabase clients fast. The simplest pattern creates one client used everywhere:
// lib/supabase.ts, imported by both server and client components
import { createClient } from '@supabase/supabase-js';
export const supabase = createClient(
process.env.NEXT_PUBLIC_SUPABASE_URL!,
process.env.SUPABASE_SERVICE_ROLE_KEY! // bypasses all RLS
// Imported in a client component? This key is now in the browser.
);
The variable name does not start with NEXT_PUBLIC_, which gives a false sense of safety. In Next.js, any server file imported by a client component exposes its runtime values to the bundle. The boundary is the import chain, not the variable prefix.
Fix: Two separate clients. The client-facing Supabase instance uses the anon key and is the only one imported by client components. The admin client uses the service role key and lives in a file that begins with import 'server-only'. Next.js will throw a build error if that file is ever imported from a client component.
4. BOLA and IDOR, the Vulnerability Type Behind the Lovable Incident
Like RLS failures, BOLA is uncommon in raw Ubserve scan counts but responsible for some of the most damaging documented vibe coding breaches, so we're citing the public incident record here rather than our own sample size.
Broken Object Level Authorization (BOLA) is the vulnerability class behind Lovable's 48-day security incident in early 2026. Any user with a free Lovable account could access another user's projects, source code, and database credentials with five API calls.
BOLA is what happens when your app checks that a user is authenticated, that they have a valid session, but does not check that they own the specific resource they are requesting. The check answers "are you logged in?" instead of "do you own this?"
// The AI-generated pattern that causes BOLA
export async function GET(req: Request) {
const session = await getSession(req);
if (!session) return new Response('Unauthorized', { status: 401 });
const { projectId } = await req.json();
// Returns the project to any authenticated user,
// regardless of whether they own it.
const project = await db.projects.findUnique({ where: { id: projectId } });
return Response.json(project);
}
// The fix: bind the query to the authenticated user
export async function GET(req: Request) {
const session = await getSession(req);
if (!session) return new Response('Unauthorized', { status: 401 });
const { projectId } = await req.json();
// Only returns the project if it belongs to the requesting user
const project = await db.projects.findUnique({
where: { id: projectId, userId: session.user.id }
});
if (!project) return new Response('Not found', { status: 404 });
return Response.json(project);
}
BOLA is invisible in happy-path testing because you always request your own resources. It only appears when someone requests a resource they did not create.
Fix: Every query that retrieves a user-owned resource must include the authenticated user's ID in the WHERE clause. Never look up a resource by ID alone and verify ownership after. Combine both constraints in a single query. This is the most important authorization pattern in any vibe-coded app.
5. Unprotected API Routes and Server Actions
AI-generated codebases accumulate routes. A feature built in week two, a data export added in week six, an admin utility created for debugging and never removed. Routes that were "temporary" but shipped. By launch, most vibe-coded apps have several API routes with no authentication check.
// What AI tools generate when you ask for a data endpoint
export async function POST(req: Request) {
const { userId, data } = await req.json();
await db.insert('records', { userId, data });
return Response.json({ success: true });
}
// No auth check. Anyone with the URL can write to your database.
Server actions in Next.js have the same problem. The "use server" directive does not add authentication. It marks a function as server-executable. Authentication is a separate concern the AI does not add by default.
Across 876 real Ubserve scans, unprotected API endpoints and unauthenticated database tables together show up in roughly 12.5% of scanned apps, and Supabase tables specifically accessible without auth appear in 11.4% of scans on their own. The most common unprotected paths: /api/admin, /api/debug, /api/internal, and any route with test or dev in the name.
Fix: A shared auth guard function at the top of every route handler and server action. In Next.js, middleware at the routing layer enforces authentication before requests reach handlers, and catches routes that were added or modified without the guard being updated.
6. No Rate Limiting on Any Endpoint
AI-generated apps ship with zero rate limiting by default. Every endpoint (login, sign-up, AI proxy, data export, password reset) accepts unlimited requests at unlimited speed from any source.
The consequences: login endpoints are brute-forceable with automated tools. AI proxy routes can be called thousands of times per minute, running up your OpenAI or Anthropic bill in hours. Paginated data endpoints can be scraped to extract your entire user database. Password reset flows can be flooded for denial of service.
Fix: Rate limiting on at minimum four endpoint types: auth flows (login, signup, password reset), AI proxy routes, data export endpoints, and any publicly accessible mutation endpoint. Upstash Redis works for distributed rate limiting across Vercel Edge and serverless functions.
7. Debug Routes and Admin Panels Left Open
AI tools create debug routes when you ask them to test things. They create admin panels when you ask for internal tooling. These are built for development convenience and are almost never locked down before launch.
Fix: Before launch, list every file in your app/api/ directory and confirm each one either has an explicit auth check or is intentionally public. Remove debug routes entirely, do not comment them out, do not gate them with if (process.env.NODE_ENV !== 'production'). Remove them. Our pre-deploy security checklist walks through this audit step by step.
8. Missing Security Headers
The single most common finding across every scan we run: 83.7% of the 876 apps we scanned are missing at least one critical security header, most often content-security-policy, x-frame-options, or x-content-type-options. None of these require touching your app's logic.
Fix: Add security headers at the framework level. In Next.js, set them in next.config.ts under headers(), once, for every route.
9. No Rate Limiting Observed
35.7% of scanned apps have no rate limiting on any endpoint we could detect. This is the same risk covered in-depth above, listed here with its real frequency: over a third of vibe-coded apps are one scraping script away from a scraped database or an inflated AI-provider bill.
10. Auth Pages Cacheable
28.8% of apps serve login, signup, or password-reset pages with cache headers that allow browsers or CDNs to cache them. A cached auth page can serve a stale CSRF token or, in worse cases, leak a previously logged-in user's session state to the next visitor on a shared device.
Fix: Set Cache-Control: no-store explicitly on every auth-related route.
11. CORS Wildcard Origin
27.2% of apps allow Access-Control-Allow-Origin: * on at least one endpoint. Combined with credentialed requests, this lets any website make authenticated calls to your API on a logged-in user's behalf.
Fix: Replace the wildcard with an explicit allowlist of your production and staging domains.
12. Supabase Anon Key Exposed in the Frontend Bundle
25.6% of apps have a Supabase anon key visible in the JavaScript bundle. Worth being precise here: the anon key is designed to be public, that's how Supabase's client-side SDK works. The real risk isn't the key being visible, it's what happens when that anon key can reach tables with no RLS policy behind it. If you haven't run the Supabase security checklist yet, this is the pairing that turns a non-issue into a breach.
13. Missing Subresource Integrity (SRI)
19.1% of apps load third-party scripts without an SRI hash, meaning if that third-party CDN is ever compromised, the injected script runs on your site with no verification.
Fix: Add integrity and crossorigin attributes to every externally-hosted <script> tag.
14. JWTs Signed with HS256 Exposed in the Frontend
13.9% of apps ship a frontend that can access an HS256-signed JWT signing pattern in a way that shouldn't be client-reachable. HS256 uses a single shared secret, if that secret is ever inferable or reachable from the client, tokens can be forged.
15. Exposed Source Maps
10.4% of apps ship production source maps publicly, letting anyone reconstruct your original, unminified source code, including comments, variable names, and sometimes hardcoded logic you assumed was hidden by minification.
Fix: Disable source map generation for production builds, or restrict access to them.
16. Missing Cookie Policy, Privacy Policy, and Terms of Service
Legal-compliance gaps, not code vulnerabilities, but they show up constantly: 9.6% of apps are missing a cookie policy, and 5.7% each are missing a privacy policy or terms of service. These matter for GDPR/CCPA exposure, not just security posture.
17. Generic API Keys Exposed in Frontend Code
7.5% of apps expose an API key that isn't tied to a specific known provider pattern, still a real credential, just not one our scanner can name automatically. If you've shipped one of these, see our guide to removing exposed API keys for the fastest path to rotating it.
18. JWTs Stored in Browser Storage
6.4% of apps store JWTs in localStorage or sessionStorage instead of an HttpOnly cookie, making them readable by any script that runs on the page, including an injected one from an XSS vulnerability elsewhere.
19. DNS Missing DMARC or SPF Records
4.1% missing DMARC, 3.9% missing SPF. Without these, attackers can spoof emails that appear to come from your domain, a common vector for phishing your own users.
20. Google Maps and Resend API Keys Exposed
3.9% expose a Google Maps key, 2.5% expose a Resend key. Both are commonly restricted incorrectly, an unrestricted Google Maps key can rack up billing charges if scraped; an exposed Resend key can be used to send email as your domain.
21. Cookies Missing HttpOnly or Weak SameSite
1.8% missing HttpOnly, 1.5% with a weak SameSite value. Small percentages, but each one directly weakens session-cookie protection against XSS and CSRF respectively.
22. Missing CSRF Tokens on Forms
1.5% of apps have at least one form submission with no CSRF token, letting a malicious site trigger state-changing requests on behalf of a logged-in user.
23. Exposed Service Role Key Patterns
Only 1.6% of scans flag a service-role-shaped key value directly, but this is the one where the rarity is deceptive: it's the highest-severity finding in our entire dataset when it does appear, since a service role key bypasses every RLS policy at once. Run the free scan if you've never explicitly checked for this.
24. Exposed Stripe, OpenAI, and Postgres Connection Secrets
Each of these appeared in exactly one scan out of 876, individually rare, but catastrophic: a Stripe secret key can move money, an OpenAI key can run up thousands in charges, and a raw Postgres connection string bypasses every application-layer control entirely.
25. Public Storage Buckets
Also a single occurrence in our data, a Supabase or S3-style storage bucket set to fully public, meaning every file inside it, invoices, uploaded documents, profile photos, is downloadable by anyone who guesses or discovers a URL.
What These Vulnerabilities Look Like After Breach
The Moltbook incident follows the exact pattern that vibe coding security concerns are built around.
Moltbook launched as a vibe-coded social network in January 2026. It grew quickly. Thousands of users in the first days. Within three days, a security researcher noticed the Supabase database had no RLS configured. Every table was accessible to any authenticated user. The researcher extracted 1.5 million API authentication tokens and 35,000 email addresses. Not through a sophisticated attack, but through ordinary authenticated API calls that simply returned more data than they should.
The product worked exactly as intended. Users could post, follow, and interact. The security failure was entirely separate from functionality: no access controls meant any authenticated user could read any other user's data.
This is the pattern. Functional testing catches functional failures. It does not catch authorization failures because you always test as yourself, with your own data, using your own credentials. The failure only becomes visible when someone uses credentials that should not have access.
Platform-Level Vibe Coding Security Risks
Beyond the vulnerabilities in the code AI tools generate, the platforms themselves carry risk.
Base44's critical authentication bypass, discovered by Wiz researchers, was in the platform's own registration mechanism. Using an application's app_id, a value hardcoded into URI paths and visible in public files, anyone could register as a user in any private enterprise application built on Base44. Human resources systems, private data repositories, internal communication tools, all technically accessible to anyone who knew the URL structure. To Base44's credit, Wiz reported it responsibly and the platform patched it within 24 hours, with no confirmed evidence of real-world exploitation. It's included here as proof of what platform-level risk looks like, not as a live breach like Moltbook.
The platform-level risk is that a single vulnerability in the platform affects every application built on it. You do not have to write the vulnerable code yourself. The platform writes it for you, and you ship it.
This is not a reason to avoid vibe coding platforms. It is the reason you scan what they generate rather than trusting what they produce by default. And why platform-specific security guides exist for Lovable, Supabase, and Base44.
The Vibe Coding Security Checklist
Use this before every production deploy.
Secrets
- No API keys in any file imported by client components
- No
NEXT_PUBLIC_prefix on any sensitive value - Service role key exists only in server-only files with
import 'server-only' - Built JS bundle scanned for
sk_,key_,secret,tokenpatterns
Database
- RLS enabled on every user-facing Supabase table
- Every SELECT policy references
auth.uid() - INSERT, UPDATE, DELETE policies exist and are scoped, not just SELECT
- Denial test passed: user B cannot read user A's data
- Private storage buckets return 403 on unsigned URL access
Authorization
- Every API route and server action begins with an auth check
- Resource queries include
userId: session.user.idin the WHERE clause - No routes with
debug,admin,test, orinternalin the path that are unlocked - Middleware enforces auth at the routing layer before handlers run
Infrastructure
- Rate limiting on auth flows, AI proxy routes, and export endpoints
- Input validated with Zod on all write endpoints
- CORS configured with an explicit allowlist, no wildcard in production
- Error responses do not expose stack traces or internal paths
The full version of this checklist, with expanded tests for each item, is at our pre-deploy security checklist.
Why Manual Review Alone Is Not Enough
Manual review catches the obvious problems. The key you can see in the file, the route you remember building without auth. It misses the systematic ones: the auth check removed during a refactor, the RLS policy that looks correct but uses the wrong comparison, the API route added in a late session that the rest of the codebase forgot about.
The pattern behind most vibe coding breaches is not a single mistake. It is a single mistake that went undetected because no one was looking at that specific thing. Automated scanning looks at everything, on every deploy, without forgetting.
Ubserve starts with a free URL scan for public-surface issues: API key exposure in the frontend bundle, source maps, missing headers, verbose errors, CORS, auth-page cache headers, and light rate-limit signals. Paid reports unlock full findings and exact fix prompts. The full audit adds private checks for RLS coverage and policy correctness, service role key boundaries, unprotected routes, GitHub exposure, Supabase/Firebase configuration, and BOLA patterns.
The free scan covers the public URL surface and shows whether meaningful issues exist before signup or payment. Paid reports unlock the full details, exact fix prompts, PDF export, and deeper audit coverage.
Run the free URL scan before your next deploy. It runs in about 60 seconds and has found real vulnerabilities in apps that passed every functional test their founders ran.
Vibe coding is not the problem. Shipping without verification is the problem. The founders who avoid breaches are not the ones who code slower. They are the ones who close the gap between "it works" and "it is safe" before someone else finds it for them.
That gap is measurable. It is closeable. And the tools to close it take less time than a code review.