← AI-built apps
Guide

How to audit an AI-built app before launch

By Alastair Murdoch Last reviewed Tested on Our own AI-assisted .NET builds, 2025–2026
In short

Before an AI-built app meets real users, check eight things: passwords and keys left in the code or its history, whether the live site still thinks it's in development, every way in, whether multi-step saves succeed or fail together, two people acting at once, database load on busy pages, automated safety checks, and a second review.

2
Audit passes it took to close the gaps
160
Security warnings on third-party packages cleared
545
Real emails one test run sent
318s → 28s
Automated test run after a fix

Before you start

  • ✓Access to the full code repository, including its history
  • ✓A list of every server the app runs on, and its settings
  • ✓A staging copy you can break, with test payment keys
  • ✓Query logging or tracing switched on
  • ✓Two browsers (or two people) to test simultaneous use

1. Find the secrets, including the ones in history

Search the whole code history, not just the current files, for passwords, keys and database connection details. On our own builds we've found a live email-provider key in a settings file, and a database connection string that was removed, then accidentally committed again. History keeps deleted secrets, so change anything that was ever committed, and keep secrets in the hosting platform's settings, not the code.

2. Check which environment the live site thinks it's in

AI-built apps are usually developed in "Development" mode, and it quietly follows them to the first public server. On one of our staging servers it switched off an IP allow-list, created admin logins with well-known details, and exposed detailed error pages and a database upgrade tool. Set the environment on every server, make demo data opt-in, and keep anything that can create or delete databases out of the web app.

3. Walk every way into the app

  • Every page, including ones packages add: a login package exposed a change-password page we never meant to ship.
  • How passwords and PINs are stored: we replaced weakly hashed PINs with proper password hashing and a lockout (5 attempts per 5 minutes).
  • Whether changing the number in a document's web address opens someone else's: files behind a bare "logged in" check could be fetched in sequence.
  • Whether emailed login links and tokens expire.

4. Follow the money through one transaction

Anything that saves several things (an order, its items, a payment, an audit record) must succeed or fail as a whole. We found a deposit recorded after its order, so a failure in between left an order marked paid with no payment. Emails and other side-effects go out only after the save succeeds.

For payments, the app must tell the provider when a failure is worth retrying (a blanket "all fine" reply stops the retries), handle repeat notifications harmlessly, and regularly check for payments taken that never became orders.

5. Test what happens when two people click at once

In two windows, as two users, do the same thing at the same moment: book the last item, edit the same record, pay the same order. AI-generated code almost always checks, then acts ("is it available? then book it"), which is only safe under a lock. The companion guide, why AI-generated code breaks under real traffic, covers the fixes.

6. Count the database calls on your busiest pages

With query logging or tracing on, load the pages real users will hit and watch whether database calls grow with the number of items (the "N+1" problem). One of our pages fetched availability three times per ticket type; batching took it from about 60 database calls to about 28, and it stopped growing with the number of events.

7. Make the automated checks enforce it, then check they run

Every proposed change should automatically run the tests, scan for secrets and check third-party packages for known vulnerabilities, blocking the change rather than just warning. One pass cleared 160 vulnerable-package warnings. Then prove each check runs: our new secret scan had a broken pattern, so it failed every time and nothing after it ran until we noticed.

8. Do a second pass

The first round of fixes is rarely complete, whoever writes them. A second audit of our own build six weeks later found clash protection never connected on three kinds of record, and a booking safeguard other code went straight around. Self-review isn't proof either: an earlier performance report on one platform rated overselling, deadlocks and excessive queries as solved or low risk. All three turned out to be real.

What usually goes wrong

From our own projects, not the manual.

Our new automated check failed on every run

We added a secret-scanning step whose exclusion pattern was broken, so it errored immediately and nothing after it, including the build and tests, ever ran. Check a new safeguard by making it fail on purpose, then pass.

A test run sent 545 real emails

The tests started the real app, background jobs included, so 138 tests started 138 copies of the app that all sent email to one address. Limit which background jobs tests may run, and swap in an email sender that discards mail.

Turning off Development mode broke the database setup

The code that created demo logins also created essential reference data, so switching Development off would have left a new database unusable. Separate reference data (needed everywhere) from demo data (development only).

A secret was removed, then came back

A database connection string taken out in one commit was added back by a later commit that swept up every file. Stop tracking the settings file (or keep secrets outside the code) so it can't be committed again, and change the credential either way.

The coverage report made every change wait 8 minutes

Measuring test coverage across everything made the same 819 tests take 318 seconds in the automated pipeline. Limiting it to the app's own code and skipping generated code brought it to 28 seconds, with the same report.

Do it yourself, or get help?

If you have a developer comfortable with your stack, they can work through the checklist on a staging copy: most items take hours, not days, and how deep each one goes depends on what the app does. If nobody has reviewed the code as a whole, the app takes payments or personal data, or you're launching soon, get a second pair of eyes. The expensive problems are the ones that only appear with real users.

Get a developer on it
FAQ

Common questions

How long does it take to audit an AI-built app?

It depends on size, but the checklist itself is quick to run. The time goes on fixing what it finds, especially anything involving payments or several people acting at once.

Can't I just ask the AI to review its own code?

It helps, but a review, AI or human, isn't proof. On one of our platforms an earlier written review rated overselling, deadlocks and excessive database queries as handled; all three turned out to be real. Tests that reproduce the problem are the proof.

What's the most common problem you find?

Check-then-act logic: code that checks whether something is available, then acts on it, without locking it first. It works for one user and fails the moment two arrive at once.

Do I need to change passwords and keys if I've deleted them from the code?

Yes. Deleting a secret from the latest version leaves it readable in the code's history. Change it, then keep secrets out of the code entirely.

Want us to audit your AI-built app?

Tell us what it does and how it was built. We'll run the checklist, fix what matters and leave the checks in place.