Vibe coding security risks: the 8 holes AI-built apps ship with

The main vibe coding security risks are database tables without row level security, secret keys in the JavaScript, AI routes anyone can call, users who can read each other's data and admin pages hidden only by a redirect. They share one cause: the agent stops when the app works, the defaults are permissive, and nobody tests the live app from outside.

The team behind Keybrum's attacksUpdated 13 min read

In short

  • Most leaks in AI-built apps come from configuration, not clever exploits: a table with RLS off, a key in the bundle, a route that never checks the session.
  • The evidence is public: a 2025 scan found 170 of 1,645 Lovable apps with missing or weak RLS (CVE-2025-48757), and in January 2026 Wiz found Moltbook's database open to read and write with the public key.
  • Code scanners read the repository. Database settings, hosting config and the shipped bundle are not in it, so test the deployed app as a stranger.
  • Access control between users is the bug prompts almost never mention: sign in as a second account and try to read the first one's data.
  • This week: get the outside view, close every table, move and rotate secrets, lock AI routes and webhooks, test with two accounts, then retest after each deploy.
On this page

Why apps built by prompting leak data

Vibe coding means building an app by describing it to an AI agent, in Lovable, Bolt, Replit, v0, Cursor or Claude Code, and shipping what it produces, often without reading the code. The agent has one test for success: the screen does what you asked. Almost every security failure passes that test. A table anyone can read still shows you the right rows. A secret key pasted into the frontend makes the feature work. An admin page that sends signed-out visitors back to the login screen looks locked in your browser, even when the data behind it answers anyone.

Defaults make it worse. Postgres creates every table without row level security (RLS), the rules that decide which rows each caller may see. Supabase's docs say that on existing projects, every new table in the public schema is also granted to the anon and authenticated roles, the roles your public key and your signed-in users act as. Until someone runs alter table ... enable row level security, anyone holding the key can read and change every row. Supabase is changing that default so exposure becomes opt-in, but an agent writing a migration adds the RLS line only if it thinks of it. And the last step of a normal release, someone trying the app as a stranger and as a second user, is the step vibe coding skips.

The code is not reliably safe either. For its 2025 GenAI Code Security Report, Veracode gave more than 100 language models 80 code completion tasks that could each be done in a secure or an insecure way. The models picked the insecure one 45 percent of the time, and while newer models wrote syntactically correct code more often, their security results stayed flat. Those were short, isolated tasks rather than whole apps, but they show that working code says little about safe code.

Today's AI tools don't yet reason about security posture or access controls on a developer's behalf, which means configuration details still benefit from careful human review.
Wiz Research, on the Moltbook exposure

Is vibe coding safe? What the public evidence shows

It can be. But researchers who tested live vibe-coded apps from the outside keep finding the same holes, often enough that you should check yours. Each line below is public, with its source at the bottom of the page.

ResearchWhat was testedWhat they found
CVE-2025-48757, March 20251,645 apps from Lovable's public showcase, homepages only303 endpoints across 170 projects, about one in ten, with missing or weak RLS, exposing names, phone numbers, API keys and payment details
Wiz Research, September 2025Vibe-coded apps run by organizationsIn Wiz's words, one in five organizations exposed to systemic risks in vibe-coded apps, through four recurring flaws: login checked in the browser, secrets in client code, open tables, internal apps with no login
Escape, October 20255,600+ public apps, mostly Lovable, plus Base44, Create.xyz, Bolt.new and Vibe StudioMore than 2,000 vulnerabilities, 400+ exposed secrets and 175 instances of personal data, including medical records and IBANs
Wiz Research on Moltbook, January 2026One viral app whose founder said he did not write a line of its codeA Supabase key in the client JavaScript and RLS missing: read and write access to 1.5 million API tokens, 35,000 email addresses and private messages
Lovable disputes CVE-2025-48757, on the grounds that each customer is responsible for protecting their own app's data. Moltbook was fixed within hours of Wiz's report.

The 8 most common vibe coding security risks

These holes keep coming back in AI-built apps, and Keybrum's attacks are built around them. Most are a setting left open or a check in the wrong place.

RiskWhat a stranger can doWhere to look
1. Missing RLS or open Firebase rulesRead, change or delete rows with the public key from your bundleSQL editor, Firebase rules
2. Secrets in the bundleUse your OpenAI, Stripe or service role key, on your bill or with full database accessYour built JavaScript files
3. Unprotected AI routesSend prompts to your model on your account, without signing inAPI routes, Edge Functions
4. Broken access control between usersSign up, then read or edit other users' recordsPolicies, routes that take an id
5. Exposed filesDownload .env, the .git folder, source maps or backupsThe deployed host
6. Admin pages behind a redirect onlyOpen the admin data directly, or read the password in the JavaScriptWhere the auth check runs
7. Framework CVEsUse a published flaw in an old Next.js or React versionpackage-lock.json, npm ls
8. Webhooks without signaturesSend a fake "payment succeeded" eventThe webhook handler

1. Tables without row level security, or Firebase rules left open

Supabase and Firebase let the browser talk to the database directly, with a key that is public by design. What protects the data is RLS on Supabase, or security rules on Firebase's Firestore, Realtime Database and Storage. Supabase's docs put it bluntly: a table in an exposed schema without RLS is readable and writable by any role with a grant on it. Both public cases above, CVE-2025-48757 and Moltbook, come down to this one hole.

Check your own project by running this in the Supabase SQL editor. It only reads the catalog and changes nothing:

sql
select c.relname as table_name
from pg_class c
join pg_namespace n on n.oid = c.relnamespace
where n.nspname = 'public'
  and c.relkind in ('r', 'p')
  and not c.relrowsecurity
order by 1;
Every row is a table in public with RLS off. Add other schemas if your API exposes them.

For each table it lists, enable RLS, then add policies that tie rows to auth.uid(). With RLS on and no policy, Postgres denies everything, which is the right starting point while you write the policies your app needs. The Supabase RLS guide has policies for the common cases, the RLS checker reviews the ones you paste, and on Firebase the rules checker flags every open read or write in the rules you paste, with the Firebase rules guide for the fix.

2. Secret keys in the JavaScript bundle

When a feature needs OpenAI, Stripe or an admin database key, the shortest path to a working screen is to put the key where the code runs: in the browser. Wiz found third-party API keys and service account credentials hardcoded in the client JavaScript of vibe-coded apps, and Escape counted more than 400 exposed secrets in its sample. Variables prefixed NEXT_PUBLIC_ or VITE_ are copied into the bundle at build time, so moving a key into one of them does not hide it.

The fix is a server-side proxy: the browser calls your own API route or Supabase Edge Function, and only that function reads the key. A secret that was ever in a public bundle is burned, so rotate it with the provider instead of only deleting it from the code. The guides on API keys exposed in the frontend and what to do after a leak cover which keys must never ship and how to rotate them. The API key leak checker finds them in code or a bundle you paste.

3. AI routes anyone can call

Generated apps often get an /api/chat or /api/generate route, or an Edge Function, that forwards a prompt to a model with your key. If it does not check the session on the server, anyone who spots the route in your JavaScript can send it prompts, and you pay for each one. Wiz's Moltbook report shows the same gap in another form: with no rate limiting, anyone could register millions of agents with a simple loop.

Require a valid session inside the route itself, give each user a quota, and keep an eye on your model usage so a spike shows up in hours, not on the invoice. The unprotected AI endpoint guide shows the pattern for Next.js routes and Edge Functions.

4. Users who can read each other's data

Prompts almost never ask for this, and it is one of the bugs we see most in generated apps. A policy or an API route checks that the caller is signed in, but not that the row belongs to them. Since anyone can sign up, "signed in" means anyone. The same hole appears as a route that takes ?id=42 and returns record 42 to whoever asks: an IDOR vulnerability.

sql
alter table public.orders enable row level security;

-- Bad: any signed-in user reads every order
-- create policy "read orders" on public.orders
--   for select to authenticated
--   using (true);

-- Good: each user reads only their own orders
create policy "read own orders" on public.orders
  for select to authenticated
  using ((select auth.uid()) = user_id);
The bad policy is commented out so the block is safe to paste. Policies add up: if an open one exists, drop it, or the owner check changes nothing.

Test it the only way that shows it: create two accounts, sign in as the second, and try to open the first one's records, both in the app and by calling the API with the second account's session.

5. Files the host serves by mistake

Some hosts and build setups serve files that were never meant to be public: a .env with database passwords, a .git folder from which the source history can be rebuilt, source maps that publish your original code, database dumps and backups. Reading the repository cannot tell you which of these your live server answers. Request /.env and /.git/HEAD on your own domain and compare each answer with a page that does not exist. The exposed .env guide covers the fix per host, and the security headers checker grades your HTTP headers while you are at it.

6. Admin pages protected by a redirect only

Wiz found vibe-coded apps where the whole login ran in the browser: the password was a string in the JavaScript, and a successful login set a flag like authenticated in localStorage, which anyone can set by hand in the developer tools. It also found internal tools and admin dashboards deployed on the public internet with no login at all. A milder version is common: the admin page redirects signed-out visitors, but the API it calls answers anyone.

The check belongs where the data is read: in the API route, the server component or the database policy. Middleware alone is not enough either. CVE-2025-29927 let anyone skip authorization checks done in Next.js middleware. It was fixed in 15.2.3, 14.2.25, 13.5.9 and 12.3.5.

7. Old framework versions with known CVEs

A generated project starts from whatever versions the template or the agent picked, and nothing in the prompting loop upgrades them once the app works. Some of those versions carry critical flaws. CVE-2025-55182, published in December 2025, is a pre-authentication remote code execution flaw in React Server Components 19.0.0, 19.1.0, 19.1.1 and 19.2.0, rated 10.0 out of 10. CISA added it to its catalog of known exploited vulnerabilities two days later. Run npm ls next react-server-dom-webpack react-server-dom-turbopack react-server-dom-parcel in your project: Next.js ships its own copy of these packages, so for a Next.js app the next version is the one to compare with the advisories. npm audit lists known advisories for everything in your lockfile, and the Next.js CVE checker gives the version to upgrade to.

8. Payment webhooks that skip the signature

Stripe tells your app that a payment succeeded by calling your webhook. It signs each event in the Stripe-Signature header, and its docs ask you to verify that signature with the endpoint's whsec_ secret, using the raw request body, before you trust the event. A generated handler that parses the JSON and marks the order paid accepts a forged event from anyone who finds the URL.

ts
import Stripe from "stripe";

const stripe = new Stripe(process.env.STRIPE_SECRET_KEY!);

export async function POST(req: Request) {
  // Bad: const event = await req.json(); trusts any JSON posted here
  const body = await req.text(); // the raw body, unparsed
  let event: Stripe.Event;
  try {
    event = stripe.webhooks.constructEvent(
      body,
      req.headers.get("stripe-signature") ?? "",
      process.env.STRIPE_WEBHOOK_SECRET!
    );
  } catch {
    return new Response("Invalid signature", { status: 400 });
  }
  // event is genuine: handle it here
  return new Response(null, { status: 200 });
}
A Next.js App Router route handler. constructEvent throws on a missing or wrong signature, and the route answers 400.

The Stripe webhook guide goes further, with replay protection and the raw body setup for each framework.

Why code scanners miss live misconfigurations

A code scanner reads your repository, and several of the holes above are not in it. RLS can be switched off in the dashboard after the last commit. Whether a bucket is public, whether the host serves /.env and which version is actually deployed are all state on a server. An access control bug is valid code doing the wrong thing: the query is correct, it just answers the wrong user.

HoleWhat a code scanner seesWhat a live test sees
RLS turned off in the dashboardNothing: no file in the repo records itThe table answering the public key
Policy checks sign-in but not ownershipValid SQL, rarely flaggedA second account reading the first one's rows
Secret injected at build timeOnly the variable nameThe value in the shipped bundle
.env or .git served by the hostOut of scopeThe file, downloaded
Unsigned webhookSometimes, if a rule looks for itAn unsigned event accepted

The public cases make the same point. The scan behind CVE-2025-48757 looked only at homepages and still found 170 leaking projects. Wiz found Moltbook's open database by browsing the site like a normal user. Neither needed the source code. Both kinds of review are worth doing: reading the code finds the cause, and attacking the live app proves the effect. Keybrum's code audit includes Cloudflare's security-audit skill, then proves each finding against the running app.

What to do this week

Work in this order, which starts with what leaks the most data.

  1. 1

    Monday: get the outside view

    Paste your app into the free check to see the backend, the keys and the table names your JavaScript gives away. Write down every key and every table it lists.

  2. 2

    Tuesday: close the database

    Run the RLS query above and enable RLS on every table it returns. Replace any policy that uses true or only checks sign-in with one that compares auth.uid() to an owner column. On Firebase, replace rules that let everyone read or write.

  3. 3

    Wednesday: move and rotate secrets

    Move every secret key behind a server route or an Edge Function, then rotate it with the provider. Deleting it from the code is not enough: old builds and anyone who copied it still have it.

  4. 4

    Thursday: lock AI routes and webhooks

    Require a session and a per-user quota on every route that calls a model. Verify the signature on every payment webhook before acting on it.

  5. 5

    Friday: test as two users, then upgrade

    Create two accounts and try to reach the first one's data from the second. Check that admin pages and their API calls refuse a signed-out request on the server. Upgrade Next.js and React to patched versions.

  6. 6

    After every deploy: test again

    Each new prompt can add a table without RLS or a route without a session check. Rerun the checks after each deploy. The vibe coding security checklist lists every layer to cover before launch.

If you built on Lovable, the Lovable security guide walks through the same risks for that platform, and the CVE-2025-48757 page explains the case behind the one-in-ten figure.

Questions

Is vibe coding safe?

It is as safe as the checks you run on what it produces. The agent builds until the app works and never tests it as a stranger, so tables without RLS, keys in the bundle and missing ownership checks reach production. Test the live app signed out and as a second user, before launch and after each change.

What are the biggest vibe coding security risks?

Tables without row level security or with open Firebase rules, secret keys in the frontend, AI routes with no session check, users able to read each other's data, exposed files, admin pages protected only by a redirect, old framework versions and webhooks that skip signature checks. The first one is behind both well-known public cases, CVE-2025-48757 and the Moltbook exposure.

How often does AI-generated code have security flaws?

Often enough to review all of it. In Veracode's 2025 test of more than 100 models on 80 coding tasks, the models chose the insecure option 45 percent of the time, and newer models wrote syntactically correct code more often while their security results stayed flat. In vibe coding the bigger risk is that nobody reviews or tests the result before it ships.

Will my platform's security scanner catch these issues?

It catches some of them, so run it. A scanner sees what it can read: your code or your database settings. It cannot sign in as two users to see whether one reads the other's data, or know what your host serves at /.env. Use it, then test the deployed app from outside.

How do I check my vibe-coded app for security issues?

Start from outside: paste the address into the free check to see the keys and tables your JavaScript exposes. Then run the RLS query from this guide, test with two accounts, and request /.env on your own domain. The vibe coding security checklist covers every layer.

Sources

  1. 1.CVE-2025-48757, NIST National Vulnerability Database
  2. 2.Statement on CVE-2025-48757, Matt Palmer
  3. 3.Hacking Moltbook: AI social network reveals 1.5M API keys, Wiz Research
  4. 4.Wiz Research discovers one in five organizations exposed to systemic risks in vibe-coded applications, Wiz Research
  5. 5.Methodology: how we discovered over 2k high-impact vulnerabilities in apps built with vibe coding platforms, Escape
  6. 6.AI-generated code poses major security risks in nearly half of all development tasks, Veracode
  7. 7.Row Level Security, Supabase Docs
  8. 8.Securing your API: default privileges, Supabase Docs
  9. 9.Row Security Policies, PostgreSQL documentation
  10. 10.Receive Stripe events in your webhook endpoint, Stripe Docs
  11. 11.CVE-2025-29927, NIST National Vulnerability Database
  12. 12.CVE-2025-55182, NIST National Vulnerability Database
  13. 13.Environment variables, Next.js Docs
  14. 14.Env variables and modes, Vite

Your app is public. So are its mistakes.

Check what any attacker can already see in it, free, in ten seconds. The full attack, with proof and fixes: €49 once, or €29 a month on a plan.

or continue with Google or GitHub