---
title: "Is My AI-Built App Secure? Ten Checks Before Customers Find the Holes - George Rios"
description: "You built it with Cursor, Claude, Lovable or Bolt and customers are using it. Here are the ten checks that find the holes AI-generated code leaves: leaked keys, missing server-side authorization, open database rules, shared environments, silent failures. Which ones a free scanner catches, which need a human, and the order to fix them."
url: https://georgerios.com/articles/is-my-ai-built-app-secure
author: George Rios
---

[ All articles](https://georgerios.com/articles)

AI-Built App Audit

# Is My AI-Built App Secure? Ten Checks Before Customers Find the Holes

You built it with Cursor, Claude, Lovable or Bolt and real customers are using it. Here are the ten checks that find what AI-generated code usually leaves behind, which ones a free scanner catches, which need a human, and the order to fix them.

Published

2026-11-05

Reading time

8 min

Topic

AI-Built App Audit

Author

George Rios

**Short answer:** probably not yet, and you can find out in an afternoon. AI coding tools are very good at producing an app that runs. They are not good at the things that only fail later: they skip server-side authorization checks, leave API keys where the browser can read them, open database rules wide so the demo works, and wire up nothing that tells you when something breaks. None of that shows up while you are the only user. All of it shows up once customers, partners or an investor's reviewer arrive.

I audit AI-built apps for a living. The ten checks below are the ones I run first, in the order I run them. Each one says what to look for, how to check it yourself, and whether a free scanner will catch it. If you want the five-minute version first, the [Vibe Reality Check](https://viberealitycheck.com/) asks eight plain-English questions and needs no code access.

## The ten checks

### 1\. Secrets in the code, the bundle, or the chat history

Search your repository and your deployed JavaScript bundle for strings that look like keys: `sk_live`, `AKIA`, `eyJ`, anything named `SECRET` or `TOKEN`. Then open your browser's developer tools on the live site, go to the Network tab, and look at what your own app sends. A key that is visible there is public. Finally, remember that your prompts and the tool's chat history are a copy of your code too: if you pasted a database password into a chat to get help, that password is in a third-party log.

_Scanner catches it:_ yes, for known key formats. Tools like gitleaks or the secret scanning built into GitHub will flag most of them. They will not tell you whether a leaked key still works, or that the one in your chat history exists at all. Rotate every key you find, not just the ones you think leaked.

### 2\. Authorization on the server, not in the screen

This is the one that gets AI-built apps breached. Log in as user A, open a record you own, and note the ID in the URL or the request. Now change the ID to one that belongs to user B. If the record comes back, every customer can read every other customer's data, and the only thing that stopped them was that your menu didn't show the link. AI tools write the check in the UI because that is where the demo needed it. Repeat the same test on every write: edit, delete, export, invite.

_Scanner catches it:_ no. This is business logic. A scanner has no idea which user should see which row. A human with ten minutes and two test accounts does.

### 3\. Database rules that let the client do anything

If you are on Supabase, Firebase or any backend where the browser talks to the database directly, the rules are the whole security model. Open your row-level security policies or Firestore rules and read them. Common findings: RLS is enabled on the table but the policy is `true` for everyone; the `service_role` key is used from the client; a policy checks the user on `select` but not on `update`; a second table added later has no policy at all. Lovable and Bolt both flag some of this now. Neither can tell you whether a policy that compiles is actually correct for your product.

_Scanner catches it:_ partly. The built-in checks find missing policies. Only a review finds wrong ones.

### 4\. Admin routes guarded only by the front end

Find every route with `admin`, `internal`, `debug`, `export` or `impersonate` in it. Call each one directly with a normal user's session, and then with no session at all, using `curl` or the browser's address bar. The front end hiding a button is not a guard. The server has to refuse.

_Scanner catches it:_ no, for the same reason as check 2.

### 5\. Untrusted input, including input to your AI features

Every form field, URL parameter, webhook body and uploaded file is untrusted. Classic injection is less common in generated code than it used to be, because the tools lean on ORMs, but raw SQL still appears in reporting queries and "quick" scripts. The new version of the problem is prompt injection: if your app passes user text into a prompt that can call tools or read other data, a user can instruct the model to do things on their behalf. Treat the model's output as untrusted too.

_Scanner catches it:_ partly. Static analysis tools such as Semgrep find raw query construction. Prompt injection needs a human reading the prompt.

### 6\. Dependencies you have never looked at

Run your package manager's audit command (`npm audit`, `pip-audit`, `dotnet list package --vulnerable`) and look at the list, not just the count. AI tools pull in whatever package made the task easiest, including abandoned ones. Check the two or three that handle authentication, file uploads and payments by hand: who maintains them, when was the last release, how many people use them.

_Scanner catches it:_ yes. This is what Snyk, Dependabot and the built-in audit commands are for. Turn one on and keep it on.

### 7\. Test data that can reach real customers

Ask three questions. Do development, staging and production use the same database? The same email sending key? The same payment keys? If any answer is yes, a test you run tomorrow can email, charge or overwrite a real customer. AI-generated setups almost always start as one environment because that is what worked on day one.

_Scanner catches it:_ no. Nothing in the code is wrong. The configuration is.

### 8\. Errors nobody sees

Deliberately break something small in production, for example by calling a route with a malformed ID, and then ask: where did that error go? If the answer is "the browser console" or "a log file on the server I never open", your customers are your monitoring. Wire up an error tracker and a single alert, then make a background job fail on purpose and confirm someone is told.

_Scanner catches it:_ no. Absence of monitoring is invisible to a scanner.

### 9\. Backups that have never been restored

Backups being enabled is a checkbox. Backups working is a test. Restore last night's backup into a scratch database and open the app against it. Note how long it took and how much data you would have lost. Most teams I audit have never done this once, and about a third find that the backup is missing a table, a bucket of uploads, or the encryption key needed to read it.

_Scanner catches it:_ no.

### 10\. Nothing stops abuse, including abuse of your AI bill

Sign up five times in a minute from one browser. Hit your most expensive endpoint, usually the one that calls a language model, in a loop. If nothing slows you down, a bot will find it, and the first sign will be an invoice. Rate limits on sign-up, password reset and anything that costs you money per call are a day's work and almost never generated by default.

_Scanner catches it:_ no, though a basic load test will show it instantly.

## What a free scanner covers, and what it doesn't

Run the scanners. They are free, fast, and they catch three of the ten: leaked secrets in known formats, vulnerable dependencies, and some raw query construction. That is real value and it takes an hour to set up.

The other seven are about what your product is supposed to allow, how it is configured, and what happens when it fails. No tool knows that user A should not see user B's invoice, that staging shares a sender address with production, or that the backup has never been restored. Those need a person reading the code and testing the running system, which is what the [audit](https://georgerios.com/ai-app-audit) is.

## The order to fix things

1. **Rotate every secret you found** and move them to environment variables or a secrets manager. This is an afternoon and closes the door that is open right now.
2. **Fix server-side authorization** and database rules. This is the one that becomes a breach notification. Budget days, not hours, and test with two accounts after every change.
3. **Separate environments** so a test can no longer touch a customer.
4. **Add error tracking, one alert, and rate limits** on sign-up and on anything that costs money per call.
5. **Restore a backup** and write down what you learned.
6. **Turn on dependency scanning** and leave it on.

Notice what is not on the list: a rewrite. In the AI-built apps I audit, most of the code is fine. The gaps cluster in exactly the places above, and they are fixable in place while you keep shipping. If you want a second pair of eyes on the result, that is what the 30-day [Architecture Discovery](https://georgerios.com/ai-app-audit#process) is for: a map of what was built, each gap with the evidence behind it, and a plan ordered the way this list is.

Start with the free [Vibe Reality Check](https://viberealitycheck.com/): eight questions, five minutes, no code access. Or [book a 30-minute call](https://cal.com/georgerios/30min) and bring the one check above that worried you most.

## References

[ Back to articles](https://georgerios.com/articles) [Book a call ](https://cal.com/georgerios/30min)

---

Book a call: https://cal.com/georgerios/30min · Phone: 973-440-2441 · Services summary for agents: https://georgerios.com/llms.txt
