Ubserve Blog

Vibe Coding Security Risks: Every AI-Built App Vulnerability

Mr. BallazMr. Ballaz
April 25, 202615 min read
Focus
Vibe Coding
Risk
Critical
Stack
Supabase/Next.js
Detection
Ubserve Runtime Simulation

The 7 vibe coding security risks behind real breaches in 2026. Exposed API keys, broken RLS, BOLA. Specific fixes for Cursor, Lovable, Bolt, and Supabase.

Moltbook shipped with Supabase and no RLS. 1.5 million auth tokens exposed on day three. Lovable had a BOLA flaw open for 48 days. These aren't edge cases — they're the default output of vibe coding without a security pass.

Vibe coding security risks — every vulnerability pattern in AI-built apps using Cursor, Lovable, Bolt, and Supabase.
Vibe coding security risks — every vulnerability pattern in AI-built apps using Cursor, Lovable, Bolt, and Supabase.

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 let unauthenticated users register inside private enterprise applications.

None of these were exotic attacks. They were the predictable output of shipping AI-generated code without a security pass.

This guide covers every vibe coding security vulnerability pattern we see in production, with the data behind them, real incident references, and specific fixes for Cursor, Lovable, Bolt, and Supabase.

Jump to:


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: 45% of AI-generated code samples introduce security vulnerabilities. GitGuardian 2026: AI-assisted commits expose secrets at twice the rate of human-written code — 3.2% vs. 1.5%. Security research from early 2026: 86% of AI-generated frontends fail basic XSS security checks. In March 2026 alone, 35 CVEs were attributed directly to AI-generated code patterns.

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 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 (2025) found that adding "secure" to AI coding prompts reduces security vulnerabilities 28–42% in generated code. Persona prompting — "you are a security-aware developer" — reduces risk 47–56%. These are meaningful improvements. They still leave a substantial residual vulnerability rate. Better prompting narrows the gap. Systematic verification closes it.


The 7 Vibe Coding Security Risks That Cause Real Breaches

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 — correct. For API keys — 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, and the most common source of data exposure incidents.

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

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.

Ubserve scan data from 2026 shows 18.7% of AI-generated applications have at least one unauthenticated route the founder was unaware of at launch. The most common 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.


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, 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 accessible to anyone who knew the URL structure.

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, token patterns

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.id in the WHERE clause
  • No routes with debug, admin, test, or internal in 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.

— Mr. Ballaz, Founder of Ubserve

Related reading

FAQs

What are the biggest vibe coding security risks?+
The seven most common vibe coding security risks are: API keys exposed in frontend bundles, missing or broken Supabase RLS policies, service role keys reaching client code, BOLA/IDOR authorization failures, unprotected API routes and server actions, no rate limiting on public endpoints, and debug routes left open in production. These account for the vast majority of breaches in AI-built apps.
How dangerous is vibe coding?+
Vibe coding is not inherently dangerous, but the data is clear: 45% of AI-generated code introduces security vulnerabilities (Veracode 2025), AI-assisted commits expose secrets at twice the rate of human-written code, and documented breaches include 1.5 million tokens exposed via a Supabase database with no RLS (Moltbook, January 2026) and a 48-day BOLA exploit on the Lovable platform. The risk is not using AI tools — it is assuming they handle security by default.
Has a vibe-coded app ever been hacked?+
Yes, in multiple documented incidents. In January 2026, Moltbook was breached within three days of launch, exposing 1.5 million API tokens through a Supabase database with no row-level security. Lovable had a broken object-level authorization flaw open for 48 days. Base44 had a critical authentication bypass that let anyone register inside private enterprise applications.
What vibe coding security checks should I run before launch?+
Before every production deploy: scan your JavaScript bundle for API key patterns, verify every Supabase table has RLS enabled with policies referencing auth.uid(), confirm your service role key is not in any client-imported file, add an auth check to every API route and server action, and test that user A cannot access user B's data.
Is vibe coding secure for production apps?+
Vibe-coded apps can be secure for production, but only after an explicit security pass. AI tools generate working code optimized for functionality, not security. The security layer — auth checks, RLS policies, key boundaries, rate limiting — is always a manual responsibility that must be verified before shipping.
What vibe coding security concerns should founders have?+
The core vibe coding security concerns are: secrets leaking into the frontend bundle, BOLA vulnerabilities (user A accessing user B's data), missing database-level access controls, admin routes left open in production, and no rate limiting enabling brute force or scraping. These patterns appear consistently across Cursor, Lovable, Bolt, Windsurf, and v0 because all of them optimize for code that works, not code that's safe.
Ubserve Security

We find the vulnerabilities in your app before hackers do.

Exposed secrets, broken access paths, and real attacker-first weaknesses. Get a fast scan and fix-ready guidance without slowing release velocity.