Someone wrote this in public about an app they had built themselves:

Vibe coded so hard the entire waitlist emails were sitting in the frontend. 91 people just chilling in the Network tab.

Ninety-one email addresses, sitting in a panel that ships with every browser. They found it without reading a line of code, and the app was working the whole time. That is this page in one incident: the signup form filled, the confirmation showed, and the thing that was wrong was visible to anyone who pressed one key.

Ten checks cover what a browser and an email address can tell you about an AI-built app you own. They take twenty-two minutes. Four of the fourteen ways these apps fail are visible this way, five leave a mark you can find, and five are not visible at all.

The checks on this page were built from two sources and nothing else. The first is AxonBuild’s audit of 26 AI-built apps in June and July 2026, with a finding ledger kept over the 21 of them somebody else had built, which records what went wrong in each one and how often. The second is the current published documentation for every browser panel a check opens, read on 25 August 2026. No app was opened to write this page, so each check names a documented screen and a measured pattern rather than a demonstration, and the count beside each one is what the audits found, not a prediction about yours.

The sample behind those counts, what the 26 audits actually measured, and how the sample was built, is published separately. Read which cohort a number comes from before you use it.

What you need before you check an AI-built app yourself

Four things, all of which you already have if the app is yours: the app’s live web address, an account you own inside it, a second email address you own, and a browser with developer tools. Chrome is the one this page quotes, because its documentation names its panels precisely and dates every page it publishes.

One warning before the list. Nothing here edits a request, replays a modified one, or points at somebody else’s app. The only check that creates a record is the second account in check 6, which makes one account and one item. The rest either read what the app already sent you or ask it for something it already offers any visitor: a sign-in attempt, a reset email, an answer from the AI feature.

Six things can be wrong under an app that still works, and only some of them leave a mark you can find in a browser. The ten below are the ones that do.

#What you openMinutes
1The Network panel in developer tools, Response tab3
2The Search panel in developer tools2
3Application > Storage > Local Storage1
4A new Incognito window2
5An Incognito window plus one address copied from the Network panel3
6Two browser profiles and two accounts4
7Your own sign-in form1
8Your inbox and one password reset email2
9The Network panel, Status column2
10An Incognito window and the AI feature’s address2

Run them in that order. Cheapest first, and the one that creates data sits late on purpose.

Ten checks on an AI-built app you can run without reading code

Every check below follows the same four beats: the panel you open, the thing you do, the thing you should not see, and the audited pattern that put it on the list. Each stands on its own, so you can run three and stop.

Check 1: what the page asked for, and what came back

Open a page in your app that shows a list of your own records. Open developer tools and click the Network tab; Chrome’s own reference for the panel describes that click plainly, and the Network panel opens. Reload the page, find the request that filled the list, click it, and open the Response tab, which the same reference describes as the way to view the source code that came back.

Now read it. What you should not see in the Network tab is anything that is not on the screen behind it: other people’s email addresses, whole records where the page shows a name, fields belonging to another account, or a list of ninety-one when the page displays ten. A page that shows a summary and receives everything has handed everything to whoever opens this panel.

This is on the list because personally identifying data turned up where it should not in at least 5 of the 21 third-party apps in the finding ledger. One was a question-and-answer platform where anybody could harvest every signed-up user’s email address, the same shape as the incident at the top of this page.

Source for the panel names: Chrome’s Network panel reference, last updated 2024-10-14.

Check 2: whether a key is sitting in the files your app already sent you

Open the Search panel. On a Mac that is Command+Option+F; on Windows and Linux it is Control+Shift+F; the customize menu inside developer tools also lists it under More tools. Chrome documents it as a way to find text across all loaded resources, with the option to use regular expressions or case sensitivity. Search for key, then secret, then token, then service_role.

You should not see a real value. Variable names are fine. So are the keys a provider labels public or publishable, such as a Supabase anon key, a Stripe pk_ key or a Firebase web config, because those are built to sit in a browser. A long string next to one of those words that is not labelled public, inside a JavaScript file the app served you, is a question for the person who built the app: which service issued it, and was it meant to be in a browser? If the answer is a secret or service_role key, every visitor now has it.

Two documented limits matter. Chrome states that the Search panel does not show results from network headers and responses, and points to a separate search inside the Network panel for those. It also cannot see the repository history, where three of the ledger’s secrets were found. Plenty of people reach for View Source first; Firefox’s documentation says View Source lets you look at the HTML or XML source for the page you are viewing, and a shipped key usually sits in a script file rather than the HTML document, so that tool answers a narrower question than this check asks.

Real secrets were committed or shipped in 6 of 21 third-party apps, 3 of them permanently in the repository history and 1 handed to every visitor’s browser, which was a spam-classifier app shipping its billing key. If you find one, rotate it first and then decide where a key should actually live.

Sources: Chrome’s DevTools Search reference (last updated 2024-09-30) and Firefox’s View Source page.

Check 3: what the app is keeping inside your browser

Navigate to Application > Storage and expand Local Storage. Click a domain to view its key-value pairs, and select a pair to preview the value below the table. Those are Chrome’s own words for the path, from a page last updated on 2019-03-14.

You should not see your actual business records here: customers, orders, invoices, messages. A role name, a plan name or a price stored here is only a display copy if the server still decides them on every request; the question to ask whoever built the app is whether editing this value here changes what the server does. Anything the server has to decide for itself does not belong somewhere the person using the browser can edit.

That is the client-trusts-itself pattern, and it appeared in 10 of 21 third-party apps in the ledger. One was a customer-records dashboard that kept the entire set of records in local storage. Another was a food-delivery app where the price of every order was decided by the customer’s browser and new users chose their own role at signup.

Source: Chrome’s Local Storage reference.

Check 4: the page that should have stopped you

Open a new Incognito window and paste your admin page or your dashboard address straight into it. Chrome Help states that Chrome does not automatically sign you into your Google Account or other websites in Incognito, and that third-party cookies are blocked by default there, which is what makes the window a fair test: it arrives as a stranger.

You should not see the page render. A redirect to a sign-in screen is the pass. A blank page with a spinner that never resolves is ambiguous, and check 5 settles it.

Unauthenticated endpoints doing privileged work turned up in 11 of 21 third-party apps in the ledger, and this is the cheapest way to find the front-door version of it.

Source: support.google.com/chrome/answer/95464.

Check 5: the data behind that page

A page that redirects you is not proof that the data behind it does. Go back to the signed-in window, open the Network panel, and find the request that loaded the dashboard’s contents. Copy that request’s address. Before you use it, check the request’s method: Chrome’s documented default columns in the request list are Status, Type, Initiator, Size and Time, so the method is not one of them. It sits in the selected request’s Headers tab, which the same reference describes as the tab you use to inspect HTTP headers. This check only applies where the method is GET, because that is the only one a pasted address reproduces.

Paste the address into the Incognito window. You should not see real records come back with nobody signed in. An error, an empty list, or a refusal is the pass.

Same pattern as check 4, 11 of 21 third-party apps, and this is where its worst version lives. One retail point-of-sale app in the ledger carried a web address that would wipe every production table, guarded by nothing but a secret pasted into the query string.

There is a longer version of this check that copies the request out of the browser and sends it again as the other account. It needs a terminal, and it lives with the API checklist rather than here.

Check 6: a second account, and one record

This is the only check that writes anything. In your normal window, signed in as account A, create one record you can recognise: a note, an invoice, a message. Then open a second browser profile, sign up with your second email address as account B, and ask for account A’s record through the same path the app used to load it: open the same page or address that showed the record to account A, with the record’s identifier in it. Do it three times: read, then update, then delete, using whatever edit and delete controls that page offers when it loads. If the page will not load for account B at all, the read is denied and the other two cannot be tried from a browser, which is a pass as far as this check can see. Plenty of apps check ownership on the read and forget the other two.

You should not see account A’s record appear for account B on any of the three.

Cross-user authorization failures were confirmed in 7 of 21 third-party apps in the ledger, with row-level-security gaps in 9 of 21, and the gap between those two numbers is the reason this check is worth four minutes rather than one.

The second-account check appears here as a procedure and nothing else. What its result means, and how much safety an app carrying a real business actually needs, is a verdict, and the verdict has its own page.

Running the second-account check once tells you about today. Turning it into something that runs itself every time the app changes is a different job, and it starts by choosing which behaviour to pin first.

Check 7: five wrong passwords in a row

Go to your own sign-in form and type the wrong password five times. Then ask for a password reset three times in a row.

You should not see the fifth attempt behave exactly like the first, and you should not see three reset emails land. Something should slow down, refuse, or tell you to wait.

What a configured stack does has published defaults, and Supabase’s are a useful reference point because they are written down with numbers on them.

Documented Supabase Auth defaultLimit
Emails on the built-in email provider2 per hour
Sign-up confirmation and password recoverya 60 second window before a new request is allowed to the same user
One-time passcodes30 per hour project-wide, with the same 60 second per-user window
Verification requests360 per hour
Token refresh1800 per hour
Anonymous sign-ins30 per hour

No rate limit on the most expensive endpoint was the finding in 13 of 21 third-party apps in the ledger. One of them let anybody send login codes to any email address they liked and run up the owner’s email bill, which is what an unmetered send loop looks like when a stranger finds it before you do.

Source: Supabase’s auth rate-limits page.

Ask the app to send you a password reset or a sign-in link. Use it, and let it sign you in. Then sign out, or open a fresh private window with no session in it, go back to the same email and click the same link again. Then wait an hour and click it a third time, again from a signed-out window. The signed-out window matters: clicking the link inside a browser that is already signed in only shows you the session you already have, which proves nothing about the link.

You should not see it sign you in on the second click, and you should certainly not see it work on the third. Supabase documents magic links as working only with email addresses and being one-time use only, and states that by default a user can only request one every 60 seconds and that they expire after 1 hour. That is the behaviour a correctly configured stack has.

If your app runs on Firebase instead, the reference point is thinner. As of 25 August 2026, Firebase’s custom email action handler documentation calls the code in the link a one-time code and shows how to handle one that is invalid or expired, but states no expiry duration anywhere on the page, so how long your own link keeps working is the only answer available to you from a browser.

A link that keeps working is one more version of unauthenticated privileged work, the 11 of 21 pattern again. The sharpest case in the ledger was a medical-advice app where a valid login could be minted for a real account with no password at all.

Sources: Supabase’s passwordless email page and Firebase’s custom email handler page.

Check 9: the thing that should have failed

Submit something the app is supposed to reject. Leave a required field blank, put a negative number in a quantity, upload a file far larger than any real one. Then read the Status column in the Network panel, which Chrome documents as the HTTP response code.

You should not see a 200 on a request that changed nothing, and you should not see a screen that says it worked when it did not. Either one means the failure went somewhere and stopped.

A 200 on a request that saved nothing is a specific mechanism with a specific cause, and it is worth understanding before you decide what the failed check meant.

The half of this check a browser cannot show you is whether that failure was recorded anywhere, and setting up the recording is a short job with its own steps. That gap is the second most common finding in the whole ledger: 17 of 21 third-party apps recorded errors nowhere at all, so when a customer hits one, it disappears.

Check 10: the AI feature with nobody signed in

Open an Incognito window and go straight to the part of your app that talks to a model: the chat, the summariser, the thing that writes the description. Ask it something.

You should not see it answer, unless you decided that strangers may use it and put a spending cap and a rate limit in front of it. Without that decision written down, every answer it gives to a stranger is on your bill, and nothing about the screen tells you how many strangers found it.

This is the pattern with the highest rate in its own cohort: a denial-of-wallet path was confirmed in 12 of the 14 third-party apps in the ledger that had an AI surface at all. One was a voice-AI app whose token server would mint paid model sessions for anyone on the internet. Another was an incident-timeline tool with three separate routes running a paid model for anyone, with no login in front of any of them.

Add the ten up and it is twenty-two minutes, not twenty. The arithmetic is worth being honest about, because the four-minute check is the one people skip.

Checks you can run in a browser on your own app: what they see and what they miss

The fourteen patterns below are the failure patterns from those 26 audits, ranked by frequency, with each count stated over the group it was measured across. The verdict column is different in kind: the patterns and their numbers are measured, and whether each one is visible from a browser is this page’s assessment, not a measurement.

Pattern in the ledgerCohort and countFrom a browserCovered by
Zero working automated testsat least 23 of the 26 auditedNot visiblenone
No error tracking or alerting17 of the 21 third-party appsSymptom onlycheck 9
No deploy gateat least 17 of 21 third-party appsNot visiblenone
AI denial-of-wallet12 of the 14 apps with an AI surfaceVisiblecheck 10
No rate limit on the most expensive endpoint13 of 21 third-party appsSymptom onlycheck 7
Unauthenticated endpoints doing privileged work11 of 21 third-party appsVisiblechecks 4, 5, 8
Cross-user authorization failures7 of 21 confirmed, row-level-security gaps in 9 of 21Visiblecheck 6
Client-trusts-itself10 of 21 third-party appsSymptom onlycheck 3
Reachable known-CVE criticals9 of 26 appsNot visiblenone
Secrets committed or shipped6 of 21 third-party appsSymptom onlycheck 2
Prompt injection8 of the 14 apps with an AI surfaceNot visiblenone
PII exposureat least 5 of 21 third-party appsVisiblecheck 1
No backups, no staging, destructive footgunsexample-led, told as one app of the 21Not visiblenone
Fake or demo data presented as productexample-led, two of the 21 named in the ledgerSymptom onlynone

Four visible, five symptom only, five not visible. The symptom-only rows are the ones worth reading twice, because a browser shows you an instance and not a rate: check 3 can find one business record in local storage and cannot tell you whether the server recomputes the price when the browser lies about it, and check 2 can find one shipped key and cannot open the repository history where three of the ledger’s six secrets were sitting.

The two hardest facts in the table are both in the invisible column. The most common finding across the whole dataset, no working automated tests in at least 23 of 26 apps, cannot be seen from a browser at all. Neither can the one where the fix is usually a single version bump: 9 of 26 apps were running a framework version with a publicly known, reachable critical.

Every check here can pass and the app can still be the kind of thing you should not yet trust with a second user, a slow network, or a refund.

The check every twenty-minute list includes, and why it is not on this one

Type a script tag into your own text box and see whether a popup appears. It sits on almost every short version of this idea, including the five-step post on a professional network that ranks on the nearby phrasing and claims to catch ninety percent of AI-built apps with no source behind the number. Two of that post’s five steps are not browser checks at all: searching the project needs the project, and asking the AI to list its own vulnerable dependencies is a prompt.

The reason it is off this list is a rule this page holds to everywhere else. Every check above names a measured pattern with a denominator behind it, and input validation does not have one. The finding ledger has no corpus-wide rate for it, and at pillar level, Input, Injection and Abuse averaged 61.9 out of 100 across the 21 third-party apps, the second-best of twelve pillars. A check with no number attached would be the only item here you could not weigh against the others.

The longer competitor version has the opposite problem. variantsystems.io/blog/ai-app-production-readiness-checklist, named and not linked here because the site sells the same kind of work AxonBuild does, publishes 33 itemized checks in seven categories with good outcomes attached to each. Roughly thirty need a terminal, the repository, or an infrastructure console, and the figures it cites publish no denominators.

One check failed. What to do first

Order the repairs by consequence, not by which one frightened you most.

Cross-user access comes first, because it is the only failure where the damage is already done to somebody who is not you. If the second account came back holding the first account’s row, the rule that was supposed to stop it lives in the database, and switching it on correctly is a procedure of its own on Supabase and on Firebase. On Supabase that means writing the policy that stops it, and the same rule on Firebase lives in its own rules file. Owners find this one themselves often enough that it circulates as advice: a post in r/lovable on 27 July 2026 was titled PSA if you connected Supabase to a Lovable app, check your RLS before you share th..., which is a check named by somebody it happened to rather than by a vendor.

Next comes anything that answered while signed out, from checks 4, 5 or 8. That is a route with no guard in front of it, reachable whether or not anybody has found it yet.

Then the key from check 2. Rotate it before you do anything else, because the old value is already out and the new one is worthless until the old one stops working.

Then the bill, from checks 7 and 10. Nothing is stolen here, so the loss arrives as an invoice, which is why it gets postponed until the invoice arrives.

Last is the silent failure from check 9, which is the least urgent and the most permanent. It is the one that hides all the others from you.

Nothing on this list touches money on purpose, because what has to be true before you take the first card is a shorter list with a different order.

Whether an app needs somebody from outside to look at it at all depends on what it is carrying, which is worth settling before you go looking for a price.

The point where a person has to look at the code

Five of the fourteen patterns leave nothing on a screen you can open, and they are not the small five.

No working automated tests, at least 23 of 26 apps, is the most common finding in the dataset and invisible from outside. So is the missing deploy gate, at least 17 of 21 third-party apps, where every push goes to production with nothing checking it first. Reachable known-CVE criticals sat in 9 of 26 apps and need a dependency list and a version comparison, neither of which a browser holds. Prompt injection was live in 8 of the 14 apps with an AI surface, and its mechanism is text reaching the model’s instructions somewhere you cannot watch.

The fifth is data safety: no backups, no staging, the leftover route that deletes everything. The ledger tells that one as a story rather than a rate, because one app of the 21 carried the version where a single web request drops the production database. Whether the data survives a bad day is the one thing on the invisible list you can test yourself, and it is a drill rather than a check.

A browser can tell you that something is wrong. It can almost never tell you why, and the five things it cannot see include the two that decide whether the app survives its next change. Somebody has to open the code for those.

These ten checks describe what the app is doing today. Whether that is enough to put it in front of customers on a chosen date is a different question, with gates instead of checks.

None of this tells you what the app was built with, which is a separate set of visible signs: the shape of the web address, the wording of the errors, the domain the sign-up email came from.

The honest version of the question is the one an owner asked in public, after their thing was already running:

But what happens after that? How do people handle things like scaling, production bugs, monitoring, DB migrations, dependency updates, etc.?

Common questions about checking an AI-built app yourself

Is this the same as testing an AI application?

No. Testing an AI application usually means testing a model: seeds, temperature, evaluation runs, defect detection rates, the coverage of a generated test suite. This page is about an app built by AI, which is ordinary software with an ordinary browser in front of it. The two searches return almost entirely different pages.

The nearby phrasing, how to verify an app built with AI, drags in a third meaning: several of its results are about verifying AI-generated images and video rather than software. Pinning behaviour into tests that run themselves is a separate job with its own page on this site.

Can I run these checks on an app somebody else built for me?

Yes, and the procedure does not change. You need the live address, an account, a second email address and a browser, all of which you have if the app is yours to use. Nothing here needs the source code, the repository, or the contractor’s cooperation.

What changes is what you do next, because checking an app somebody built for you with AI is partly a relationship question. Checking work you paid somebody for adds a second question this page does not answer, which is what to ask them and what a stalling answer sounds like.

Do I need developer tools open for all ten checks?

No. Four of the ten need nothing but a browser window and an inbox: check 4 pastes an address into an Incognito window, check 7 types wrong passwords into your own sign-in form, check 8 opens an email link twice, and check 10 asks the AI feature a question while signed out. That is seven of the twenty-two minutes.

The other six use panels that ship with the browser you already have. Nothing here needs an install or a purchase.

Could I break something by running these?

Almost certainly not. Nine of the ten change nothing: they open panels, copy an address, ask the app for things it already offers a visitor, and look at what comes back. Nothing is edited, replayed, or resent in a modified form.

Check 6 is the exception, and its footprint is one extra account and one test record you created on purpose. Check 7’s wrong passwords may lock your own account for a while, which is the outcome you were hoping for.

How long does this actually take?

About twenty-two minutes of your own time for all ten, if nothing surprises you, plus one hour of waiting for check 8’s third click, which you can spend on the other checks. The table near the top of this page carries the per-check budget, and the four-minute one is check 6, because two browser profiles and two accounts take the longest to set up.

If you have five minutes rather than twenty-two, run checks 3, 4 and 7. That is four minutes and it covers three different patterns: what the browser is trusted to decide, what a signed-out stranger can open, and whether anything slows an attacker down.

Is twenty minutes enough to know my app is fine?

No, and the map above is exactly why. Twenty-two minutes covers four of the fourteen patterns properly and gives you a partial signal on five more. Five are invisible from a browser, including the most common finding in the whole dataset, and no amount of looking at a screen will surface them.

Owners ask this out loud. A thread in r/SaasDevelopers on 24 August 2026 was titled Founders who launched a SaaS: what did you actually check before you felt comforta..., which is the real question underneath the search. These ten checks are a floor.

Can my AI builder run these for me?

No, and the reason is in what the checks are rather than in the quality of the tool. Every one of them needs a second identity: a signed-out window, a second account, a mailbox, a wrong password typed by a person. A review that runs inside the builder is reading the project the builder generated.

The builder’s own security features still catch things worth catching. The ten above ask their question from outside the system that produced the app, which is the part no built-in review can do for you.

Do these checks work for a phone app?

Not most of them. A native phone app’s requests do not appear in a browser’s Network panel, and a native screen has no web address to paste into one, so checks 1, 2, 3, 4, 5 and 9 have nothing to open. The panels this page names are browser panels and they only see what a browser loaded.

Four still work, because they never needed developer tools: the wrong-password check, the used-link check, the signed-out AI check where the feature has a web address, and the second-account check run through whatever interface the app gives you. If the phone app has a web version, the whole list applies to that.