// GUIDE

7 security holes AI coding tools leave behind

Updated 2026-08-07 · 11 min read

The short answer

AI coding tools repeatedly ship seven specific holes: public database rows, secret keys in the browser bundle, auth checks that only run client-side, unsigned payment webhooks, public storage buckets, wide-open CORS, and unsanitized input that allows injection. None of them look like bugs, the app works, which is exactly why they survive to launch. Below is what each one is, why AI tools cause it, what it costs you, and the direction of the fix.

Why AI-built apps share the same seven weaknesses

AI coding tools optimise for a working demo. When you ask Lovable, Bolt, Cursor, Replit or v0 to "add a database" or "let users upload files," the fastest path to something that runs is the permissive default, open access, keys wherever they are convenient, checks in the browser where they are easy to write. The result works on the first try, which removes the usual signal that something is wrong.

These are not exotic vulnerabilities. They are the same seven mistakes over and over, because they all come from the same root cause: convenience defaults that were never tightened. Learn to recognise them and you can audit almost any AI-built app.

1. Public database rows

What it is: your database tables are readable (and sometimes writable) by anyone with the public key, because Row Level Security is off in Supabase or your Firebase rules are open.

Why AI tools cause it: to make a feature work quickly, the tool creates a table and skips the row-level policies, or explicitly disables RLS "to fix" a query that was returning nothing. The app then works perfectly, for you and for a stranger reading the same data.

The cost: every customer record, emails, orders, messages, whatever the table holds, can be downloaded by anyone who opens the network tab and reuses the public key. This is the single most common way AI-built apps leak data. [SOURCE NEEDED]

The fix: turn on RLS for every table and add a policy tying each row to its owner ("auth.uid() = user_id"); lock Firebase rules to authenticated owners. See our dedicated RLS guide for good-vs-bad policy examples.

2. Secret keys in the browser bundle

What it is: a secret key, Supabase "service_role", a Stripe "sk_" key, an OpenAI key, an SMTP password, ends up in code that ships to the browser.

Why AI tools cause it: the tool needs a key to call a service and places it in the frontend where the calling code lives, sometimes behind a "NEXT_PUBLIC_" variable name that forces it into the public bundle. It works, so no one notices the key is now public.

The cost: a service_role key bypasses all your database rules. A leaked Stripe or OpenAI key can be used to run up charges on your account. Anyone who views source can copy it.

The fix: rotate the exposed key immediately, then move it to a server-side environment variable or a serverless/edge function. Only publishable keys (Stripe "pk_", Supabase "anon") belong in the browser.

3. Client-side-only auth checks

What it is: the decision about whether a user is allowed to see a page or use a feature happens in the browser, a hidden button, a redirect, a conditional render, with nothing enforcing it on the server.

Why AI tools cause it: hiding a button when "user.role !== admin" is the most visible, easiest-to-generate way to "add permissions," and it looks correct in the preview.

The cost: anyone can bypass a check that only runs in their own browser. They visit the protected URL directly, or edit the request, and reach admin tools or paid features for free.

The fix: enforce every permission on the server, in your database rules (RLS / Firebase) or inside your API route. Client-side checks are fine for UX (hiding things), never for security.

4. Unsigned payment webhooks

What it is: your payment webhook (the URL Stripe or Polar calls when a payment succeeds) accepts any incoming request and acts on it without verifying it really came from the payment provider.

Why AI tools cause it: the tool wires up a route that reads the event and grants access, but skips the signature-verification step because the happy path works without it.

The cost: anyone who discovers the webhook URL can send a fake "payment succeeded" event and unlock paid access, credits, or entitlements without paying. [SOURCE NEEDED]

The fix: verify the provider signature on every event using your webhook signing secret before you trust it, and confirm the amount and currency match what you expected.

5. Public storage buckets

What it is: a file storage bucket (Supabase Storage or Firebase Storage) is set to public, or its rules let any logged-in user read any file, and it holds private content.

Why AI tools cause it: public is the simplest setting that makes uploaded images and files load without extra plumbing, so that is what gets generated.

The cost: private uploads, ID documents, invoices, user photos, exports, become accessible to anyone with (or who can guess) the URL. File URLs are often predictable.

The fix: make private buckets private, scope storage rules to the file owner, and serve private files through short-lived signed URLs instead of public links.

6. Wide-open CORS

What it is: your API responds to requests from any website ("Access-Control-Allow-Origin: *"), including authenticated endpoints.

Why AI tools cause it: "allow everything" is the default that removes CORS errors during development, so it gets left in.

The cost: it widens the attack surface, other origins can call your API in contexts you never intended, which compounds the damage of any of the auth or key issues above.

The fix: restrict CORS to your own domain(s), and while you are in the config, add standard security headers (HSTS, X-Content-Type-Options, a Content-Security-Policy).

7. Unsanitized input and injection

What it is: user-supplied input flows into a database query, a shell command, or the page without being safely handled, the classic setup for SQL injection or cross-site scripting.

Why AI tools cause it: when generated code builds a query by gluing strings together with user input, or renders user input as raw HTML, it works in the demo and hides the injection risk.

The cost: an attacker can craft input that reads or destroys data, or runs script in other users' browsers. [SOURCE NEEDED]

The fix: use parameterised queries or the database client's query builder (never string-concatenated SQL), and escape or sanitise any user input before rendering it. Supabase's client and most ORMs do this for you when used as intended.

Key takeaways

  • The seven holes share one root cause: convenience defaults from the build stage that were never tightened before launch.
  • Public database rows are the most common and most damaging, they leak every record to anyone with the public key.
  • Secret keys in the browser bundle must be rotated and moved server-side; only publishable keys belong in the frontend.
  • Auth and payment checks that run only in the browser can always be bypassed, enforce them on the server.
  • Unsigned webhooks let anyone fake a successful payment; always verify the provider signature and the amount.
  • None of these look like bugs, which is why they survive to production, deliberately checking for them is the only reliable catch.

Frequently asked

Does my app have all seven of these?

Most AI-built apps have at least one or two, rarely all seven. The point is to check each deliberately, because a working app gives you no signal about which are present.

Which of the seven should I fix first?

Public database rows and secret keys in the bundle, in that order, they leak the most data and cost the most money, and they are the fastest to exploit.

Are these unique to AI coding tools?

The vulnerabilities themselves are classic and predate AI. What is specific to AI tools is how reliably they ship the permissive-default version, because the generated code works immediately and hides the gap.

Can a scan find all seven?

A connected (white-box) scan of your repo can flag all seven categories. A free URL scan catches the ones visible from outside, exposed keys, open databases, public files, and CORS.

Run a free security scan

Paste your app's link and get a plain-English A–F grade in about 60 seconds, plus the exact fix for every issue.

Free · No signup · Your code stays yours · Results in ~60s