Ask AI for an app and you get a working app: a login, a database, a payment page. Whether any of it is safe is a question it only answers if you ask.
This page lists 30 holes that show up again and again in AI-built apps. They are grouped in 6 sets, in the order a visitor meets them. Each has a plain explanation, a check and a fix.
Not sure where to begin? Run the prompt below. Your AI reads your code, reports what it finds with the file and line, and changes nothing until you say so.
AI builds it. You check the locks.
// Build this with your AI agent
Build this with your AI agent
Want to try this? Copy the setup prompt into your coding agent with this guide's link.
Read this guide: https://codewithnishant.dev/free/30-security-holes-ai-never-checks/ and the OWASP pages it links to. Audit the code in this project against the 30 holes in the guide. For each hole say whether it is found, not found or not applicable, and why. For every finding give the file and line, how serious it is (high, medium or low) and the smallest fix. Do not change any file until I approve a fix. Never print or store secret values: if you find one, say where it is and tell me to rotate it. Do not run anything against live systems, production data or third-party services. If you cannot check something from the code alone, say so and tell me what to check by hand. At the end, give me the 5 findings to fix first.
01. How to use it
Three steps
- Copy the prompt above and run it in your project.
- Read the findings. Skip the holes that do not apply to your app. Use the Check line in the matching section to confirm the ones that do.
- Fix one at a time. Ask: fix finding 3 only and show me the change. Then run the audit again.
What a good result looks like (an example of the format, not from a real project)
| Hole | Where | How serious | Smallest fix |
|---|---|---|---|
| 14. Change one ID | src/api/orders.ts:42 | High | Check the order belongs to the signed-in user |
| 22. No rate limits | src/api/login.ts:10 | Medium | Limit tries per account and per address |
02. The 30 at a glance
The short version of each
| # | Hole | The short version |
|---|---|---|
| 1 | Weak sessions | Stolen or reused login cookie |
| 2 | Weak JWT secrets | Guessable token signing secret |
| 3 | Broken password reset | Reset links that can be reused |
| 4 | No MFA | One password is all it takes |
| 5 | Login that tells attackers who has an account | Messages reveal real users |
| 6 | Default passwords left on | admin / admin still works |
| 7 | Private data in local storage | Any script can read it |
| 8 | Cross-site scripting | Script in a comment runs for everyone |
| 9 | Unsafe file uploads | Any file accepted |
| 10 | Path traversal | ../ steps out of the folder |
| 11 | Server-side request forgery | Your server fetches any URL |
| 12 | APIs that trust whatever the user sends | Changed price accepted |
| 13 | Open redirects | Your link, their page |
| 14 | Change one ID and read someone else's data | Order 101 becomes 102 |
| 15 | Payment checks only on the front end | API still serves paid content |
| 16 | Other sites sending requests as your logged-in user | Another site rides your cookie |
| 17 | Any website allowed to call your API | CORS allows everyone |
| 18 | Unprotected GraphQL and WebSockets | The extra doors have no lock |
| 19 | Webhooks with no signature that can be replayed | Fake or repeated events |
| 20 | Race conditions on payments | Two requests, one balance |
| 21 | Business logic abuse | Allowed steps, broken rules |
| 22 | No rate limits | Bots can try forever |
| 23 | Test and staging left public | Test copy open to the internet |
| 24 | Deploy keys exposed in CI | Keys in logs, tokens too strong |
| 25 | Unpinned GitHub Actions and packages | Bad update, no review |
| 26 | Security checks that fail open | A broken check lets people in |
| 27 | No timeouts | One slow call hangs the app |
| 28 | AI features leaking private data | Other people's data in the prompt |
| 29 | Running AI output without checking it | AI text treated as trusted |
| 30 | AI agents with too much access | One wrong step deletes real data |
03. Login and sessions
Who you are, holes 1 to 7
1. Weak sessions
- What goes wrong: The cookie that keeps you logged in can be stolen or reused. It never expires, it is not marked secure, or it stays the same after login.
- Check: Open dev tools and look at the session cookie. Is it HttpOnly, Secure and SameSite? Does it expire? Does it change after login?
- Fix: Use your framework's session tool, set those flags, give sessions an expiry and issue a new session id on login.
Source: Session Management Cheat Sheet
2. Weak JWT secrets
- What goes wrong: Tokens are signed with a short or guessable secret like secret or 1234. Anyone who guesses it can make a fake token and log in as anyone.
- Check: Find where tokens are signed. Is the secret a long random value from an environment variable? Does verification allow only the algorithm you chose?
- Fix: Use a long random secret (32 bytes or more) in an environment variable, allow one named algorithm and set a short token expiry.
3. Broken password reset
- What goes wrong: Reset links that can be guessed, reused or never expire let someone else take over an account.
- Check: Request a reset, use the link, then try it a second time. Does it still work? How long does it live?
- Fix: Make reset tokens random, single use and short lived, store them hashed, and give the same reply whether or not the email exists.
Source: Forgot Password Cheat Sheet
4. No MFA
- What goes wrong: One stolen or guessed password is all it takes. There is no second step.
- Check: Can you log in as an admin with a password alone?
- Fix: Offer an authenticator app or passkeys, and require them for admin accounts first.
5. Login that tells attackers who has an account
- What goes wrong: Messages like no such user, or a signup that says this email is taken, let attackers build a list of your real users.
- Check: Try login, signup and forgot password with a real and a fake email. Do the messages or response times differ?
- Fix: Use the same message and similar timing in both cases, for example: if the account exists, we sent an email.
Source: Authentication Cheat Sheet
6. Default passwords left on
- What goes wrong: Admin accounts, database users or sample data that still use the default login.
- Check: Search the code and seed files for default users and passwords. Try the default login on every admin page.
- Fix: Remove sample accounts, force a strong password at first setup and never ship a default credential.
Source: Authentication Cheat Sheet
7. Private data in local storage
- What goes wrong: Anything in local storage can be read by any script on the page. One XSS bug and the tokens are gone.
- Check: Open dev tools, Application tab, Local Storage. Do you see tokens or personal data?
- Fix: Keep session tokens in HttpOnly cookies and keep personal data on the server.
Source: HTML5 Security Cheat Sheet
04. Input and uploads
What users send in, holes 8 to 13
8. Cross-site scripting
- What goes wrong: User text is shown on the page as code, so a script in a comment runs in every visitor's browser.
- Check: Search for innerHTML, dangerouslySetInnerHTML and templates that skip escaping. Post <b>test</b> in a form and see if it shows up bold.
- Fix: Escape output by default, sanitize any HTML you must allow and add a Content Security Policy.
Source: XSS Prevention Cheat Sheet
9. Unsafe file uploads
- What goes wrong: The app accepts any file, so someone uploads a script, a huge file, or a file that looks like an image but is not.
- Check: Try uploading a .php or .html file renamed as a picture. Is it accepted? Where is it stored and who can open it?
- Fix: Allow only the types you need, check size, rename the file, store it away from your app code and never run it.
Source: File Upload Cheat Sheet
10. Path traversal
- What goes wrong: A file name from the user is added to a path, so ../../ steps out of the folder and reads other files.
- Check: Find every place a user value becomes a file path. Try ../../etc/passwd as the value.
- Fix: Never use user input as a path. Look files up by id, or resolve the path and check it stays inside the allowed folder.
Source: Path Traversal (OWASP)
11. Server-side request forgery
- What goes wrong: Your server fetches a URL the user gave it, so it can be pointed at internal addresses that only your server can reach.
- Check: Find features that fetch a URL, like link previews, image import and webhooks. Try an internal address such as http://localhost or a private IP.
- Fix: Allow only known hosts, block private and cloud metadata addresses, and check the address after the DNS lookup.
Source: SSRF Prevention Cheat Sheet
12. APIs that trust whatever the user sends
- What goes wrong: The server believes the request: price, role, user id, quantity. Change the value and it accepts it.
- Check: Send a request with a changed price, role or user id. Does the server accept it?
- Fix: Validate every field on the server. Never take price, role or owner from the request body, look them up yourself.
Source: Input Validation Cheat Sheet
13. Open redirects
- What goes wrong: A link like ?next=https://evil.example sends people from your trusted domain to a fake page.
- Check: Find redirect parameters such as next, return and url. Try an outside address.
- Fix: Only redirect to a fixed list of paths or addresses you own.
05. Access and data
Who can touch what, holes 14 to 18
14. Change one ID and read someone else's data
- What goes wrong: You open /orders/101, change it to 102 and see another customer's order. The server never checks who owns it.
- Check: Log in as user A, copy the link to a record, then open it as user B. Try this on every endpoint that takes an id.
- Fix: Check ownership on the server for every read and write, and add database access rules for each table.
Source: IDOR Prevention Cheat Sheet
15. Payment checks only on the front end
- What goes wrong: The page hides the premium button, but the API still serves premium content to anyone who calls it.
- Check: Call the paid API directly without paying. Does it answer?
- Fix: Check the subscription or payment on the server for every protected request.
Source: OWASP Top 10:2025
16. Other sites sending requests as your logged-in user
- What goes wrong: Another website makes your logged-in user's browser send a request to your app, and your app trusts it because the cookie came along.
- Check: Do state-changing requests (POST, PUT, DELETE) work from another origin with only the cookie? Are cookies SameSite?
- Fix: Set SameSite on cookies and require a CSRF token on state-changing requests.
Source: CSRF Prevention Cheat Sheet
17. Any website allowed to call your API
- What goes wrong: CORS is set to allow every origin, so any website can call your API from a visitor's browser.
- Check: Look at the Access-Control-Allow-Origin header. Is it * or does it repeat whatever origin asks?
- Fix: Allow only your own origins by name, and never combine a wildcard with credentials.
Source: HTML5 Security Cheat Sheet
18. Unprotected GraphQL and WebSockets
- What goes wrong: A GraphQL endpoint with no login or limits, or a WebSocket anyone can connect to.
- Check: Can you open the socket or send a GraphQL query without logging in? Is introspection on in production? Can one query ask for everything?
- Fix: Require login on connect and on each message, turn off introspection in production and limit query depth and size.
Source: GraphQL Cheat Sheet
06. Payments and automation
Money and webhooks, holes 19 to 22
19. Webhooks with no signature that can be replayed
- What goes wrong: Anyone who finds the webhook URL can send fake events, and a real event can be sent again.
- Check: Does the handler verify the signature header? Does it ignore an event id it has already processed?
- Fix: Verify the signature with the provider's library, check the timestamp and store event ids so repeats are ignored.
Source: Stripe: webhook signatures
20. Race conditions on payments
- What goes wrong: Two requests arrive at the same moment and both pass the check before either updates the balance, so a coupon works twice or money is spent twice.
- Check: Send the same request twice at once. Do the balance, stock or coupon count go wrong?
- Fix: Use database transactions, row locks or unique constraints, and idempotency keys on payment calls.
Source: PortSwigger: race conditions
21. Business logic abuse
- What goes wrong: Every step is allowed on its own, but the order or the volume breaks your rules: stack coupons, refund after use, order minus one item.
- Check: List your rules in plain words (one coupon per order, refund only once) and try to break each one.
- Fix: Enforce each rule on the server and write a test for every abuse case you thought of.
22. No rate limits
- What goes wrong: A bot can try thousands of passwords, codes or sign-ups, or hammer a costly endpoint, with nothing to slow it down.
- Check: Try ten wrong passwords in a row. Does anything stop you? Try the same on reset and code checks.
- Fix: Limit tries per account and per address on login, reset, codes and costly endpoints, and slow down after failures.
Source: OWASP API Security Project
07. Deploy and CI
How it ships, holes 23 to 27
23. Test and staging left public
- What goes wrong: A test copy of the app is open to the internet, often with real data and weaker settings.
- Check: Can you open your staging address without logging in? Does it hold real customer data?
- Fix: Put staging behind a login, use fake data and keep it out of search engines.
Source: OWASP Top 10:2025
24. Deploy keys exposed in CI
- What goes wrong: Keys printed in build logs, or tokens with far more power than the job needs, let anyone who sees them take over your deploys.
- Check: Search your CI logs and config for keys. Check what each token is allowed to do.
- Fix: Give each job the smallest token, mask secrets, use short-lived credentials and rotate any key that showed up.
25. Unpinned GitHub Actions and packages
- What goes wrong: uses: some/action@main, or a package set to latest, means a bad update lands in your build with no review.
- Check: Look at your workflow files and lockfiles. Are Actions pinned to a commit and packages locked?
- Fix: Pin Actions to a full commit, commit your lockfile and review updates before accepting them.
26. Security checks that fail open
- What goes wrong: When the check itself breaks or times out, the app lets the request through.
- Check: Switch off the auth or payment service in a test. Does the app let people in?
- Fix: Default to deny: if a check cannot finish, the answer is no.
Source: OWASP Top 10:2025
27. No timeouts
- What goes wrong: One slow service makes your whole app wait forever, which ties up resources and can take it down.
- Check: Find outgoing calls and database queries. Is there a timeout on each?
- Fix: Set a timeout on every outside call and query, and cap retries.
Source: OWASP API Security Project
08. AI features
The new doors, holes 28 to 30
28. AI features leaking private data
- What goes wrong: Other people's data, or secrets, end up in the prompt, the logs or the answer.
- Check: Ask the AI feature for another user's data. Look at what goes into each prompt and what is logged.
- Fix: Send the model only the signed-in user's data, never put secrets in prompts and redact what you log.
29. Running AI output without checking it
- What goes wrong: Code, queries or commands written by the AI are run, or its HTML is shown, as if they were trusted.
- Check: Find every place AI output is executed, queried or shown on a page.
- Fix: Treat AI output like user input: validate it, sandbox it and ask a person before anything risky runs.
30. AI agents with too much access
- What goes wrong: An agent holds a token that can change production data, so one wrong step deletes real things.
- Check: List every tool and token the agent has. Which ones can write to production?
- Fix: Give agents read-only access by default, keep production out of reach and require approval for deletes. Keep backups.
09. What went wrong for real
Reported by others, matched to the closest hole
These are not my projects. Each row is what the outlet reported, and the closest hole on this page. I did not test any of these myself.
| Who | What was reported | Closest hole | Source |
|---|---|---|---|
| Lovable | Tenable's page for CVE-2025-48757 describes a database access-rule problem in Lovable that lets unauthenticated attackers read or write tables of generated sites, and rates it critical. Lovable's side, as Tenable quotes it: each customer is responsible for protecting their own app's data. | Hole 14: who can touch what | Tenable: CVE-2025-48757 |
| Base44 | Wiz found that, with only a non-secret app id, an attacker could use undocumented registration and email verification endpoints to create a verified account on a private app, which skipped SSO. The Hacker News reports it was disclosed on 9 July 2025, fixed within 24 hours, with no evidence it was exploited. | Hole 12: an API that trusts what it is sent | The Hacker News: Base44 access bypass |
| Tea | CyberInsider reports attackers reached an unprotected legacy storage system. About 72,000 images were exposed, around 13,000 of them selfies and government IDs. | Hole 14: who can read stored data | CyberInsider: Tea app breach |
| Replit | The Register reports that SaaStr's founder said Replit's AI agent deleted his production database during a code freeze, and that the agent said a rollback was impossible when it was not. | Hole 30: agents with too much access | The Register: Replit database deletion |
10. Make it a habit
One audit is a start
- Run it before every release and after any big change to login, payments, uploads or an AI feature.
- Write the rules down once. The 8-file cheat code has a SECURITY.md template, so your AI reads these rules before it writes code.
- Check the build order. The 19 layers AI skips page covers what to build and in which order.
- Want a longer checklist? The 25 vibe coding safety checks page works as a second pass.
11. FAQ
What are the 30 security holes?
They are 30 common ways an AI-built app ends up unsafe: weak sessions, weak JWT secrets, broken password reset, no MFA, a login that tells attackers who has an account, default passwords, private data in local storage, cross-site scripting, unsafe file uploads, path traversal, server-side request forgery, APIs that trust user input, open redirects, changing one ID to read someone else's data, payment checks only on the front end, CSRF, any website allowed to call your API, unprotected GraphQL and WebSockets, unsigned and replayable webhooks, race conditions on payments, business logic abuse, no rate limits, public test and staging sites, exposed deploy keys, unpinned GitHub Actions and packages, security checks that fail open, no timeouts, AI features that leak private data, running AI output without checking it, and AI agents with too much access.
Can an AI really audit my code?
It can read your code and flag many of these patterns, which makes it a useful first pass. It cannot test how the live app behaves, and it can miss things or flag things that are fine. Treat the result as a list to check, not a clean bill of health, and use the Check line in each section to confirm by hand.
Is it safe to give my code to an AI agent?
That depends on the tool and your plan, because many coding agents send your code to a cloud model. Check your tool's data settings and policy, and keep secret values out of what it reads. The prompt on this page tells the agent not to print secrets and not to touch live systems.
Do I need to fix all 30?
No. Some will not apply, for example no payments means no payment holes. Fix the ones the audit finds, start with the high ones, and run the audit again after each fix.
How is this different from the 25 vibe coding safety checks page?
That page is a checklist you work through after you have built something. This one is 30 named holes in 6 groups, each with a check and a fix, plus a prompt that makes your AI report the exact file and line. The two work well together.
Does the prompt work in Claude Code, Codex and Cursor?
It is plain text written for coding agents, so it should work in any of them. I have not tested it in every tool, and the results will vary with the model you use.
How often should I run the audit?
Before each release and after any big change, especially anything that touches login, payments, uploads or an AI feature.
12. Sources and what I checked
Checked 17 October 2026
Docs and news pages change. Recheck them before you rely on them.
- OWASP Top 10:2025
- Session Management Cheat Sheet
- JSON Web Token Best Current Practices (RFC 8725)
- Forgot Password Cheat Sheet
- Multifactor Authentication Cheat Sheet
- Authentication Cheat Sheet
- HTML5 Security Cheat Sheet
- XSS Prevention Cheat Sheet
- File Upload Cheat Sheet
- Path Traversal (OWASP)
- SSRF Prevention Cheat Sheet
- Input Validation Cheat Sheet
- Unvalidated Redirects and Forwards Cheat Sheet
- IDOR Prevention Cheat Sheet
- CSRF Prevention Cheat Sheet
- GraphQL Cheat Sheet
- Stripe: webhook signatures
- PortSwigger: race conditions
- OWASP: business logic vulnerability
- OWASP API Security Project
- GitHub: security hardening for Actions
- OWASP Top 10 for LLM Applications
- Tenable: CVE-2025-48757 (incident report)
- The Hacker News: Base44 access bypass (incident report)
- CyberInsider: Tea app breach (incident report)
- The Register: Replit database deletion (incident report)
What I checked, and what I did not
I read the sources above on 17 October 2026 and wrote each check and fix from them. The prompt and the one-line checks are my own wording. I did not run the audit prompt on a real project for this page, and I give no numbers on how many holes it will find. An AI audit is a first pass. It can miss things and it can flag things that are fine.
AI builds fast. Thirty checks later, you know where the locks are.
// Free newsletter
I send out guides like this every week
Real setups, real sources, no hype. Drop your email and I'll send you the next one.