The tools that let anyone ship a web app in an afternoon are very good at one half of authentication and quietly bad at the other. They wire up the login screen, the OAuth button, the “sign in with Google” flow. What they skip is the part with no visible UI: the check that runs after login to decide whether this visitor is allowed to see this data.
So the front door gets a lock and the back door gets left open. The dashboard renders its authenticated view to a logged-out browser. The API returns the full records table to a request with no token. This is broken access control, OWASP's number one web application risk since 2021, and it is the most common serious flaw we find in AI-built apps. We decided to measure how common.
What we did
We took 2,736 real, deployed apps, pulled from public directories of recently shipped projects, and for each one we did what any visitor's browser already does. We requested its private routes with no session,/dashboard, /admin, /account and the like, and we asked its own API and database endpoints for data with no token. If access control is doing its job, a logged-out request to those surfaces comes back empty or with a redirect to login. If it is not, the app hands back a private page or real rows to an anonymous request.
This is not an attack. It is the exact request the app itself is happy to answer, using nothing a normal browser does not already send. We read only enough to confirm a surface was exposed, stored none of the returned data, and we are naming no apps.
Scan your own app for issues like these
Paste your live URL. We check what your app serves publicly for exposed keys and misconfigurations. No account, no install.
What we found
Of the 2,736 apps we checked, 124 served private surface to an anonymous visitor. That is about one in twenty-two, 4.5 percent, with no exploit and no password guessing involved. We just asked, and they answered. The exposures fell into three patterns:
| What was open | Apps | Severity | What a stranger could reach |
|---|---|---|---|
| Dashboard & account pages | 89 | High | The logged-in view of /dashboard, /admin or /account, rendered to a visitor who never signed in. |
| APIs returning data | 25 | Critical | Backend endpoints replying with real records, user lists, orders, submissions, to a request with no auth header. |
| Public databases | 10 | Critical | Supabase tables with row level security off, readable directly with the browser's own key, bypassing the app. |
The 89 open pages are the “looks fine, isn't” case: the app appears to require a login because there is a login screen, but the screen is decoration. The 35 in the bottom two rows are the ones that keep founders up at night, because a stranger with a browser's dev tools can read the underlying data with no account at all. The difference is a window with the blinds up versus a filing cabinet left unlocked in the lobby.
This is an early sample, not a census, and we will keep widening it. But better than four percent of live apps leaving a private surface open is not a rounding error. The point is not that AI builders are unsafe. It is that whether any given app is safe comes down to a check that has no visible UI, is easy to skip, and stays invisible until someone looks.
How we checked, exactly
The whole method is a request anyone could send from a terminal:
# request a private route with no session
$ curl https://an-app.example/dashboard
200 OK -> full authenticated dashboard rendered
# hit its API with no token
$ curl https://an-app.example/api/users
200 OK [{"email":"...","role":"admin"}, ...]
# a properly-locked app answers like this instead
$ curl https://a-safe-app.example/api/users
401 UnauthorizedA correctly built app answers a logged-out request to a private surface with 401, 403, or a redirect to login. The 124 answered with 200 and the goods.
Why it keeps happening
Ask an AI assistant to “add login” and it will. It builds the sign-in page, the session, the redirect. That is authentication, proving who you are. The part it routinely omits is authorization, enforcing what you are allowed to touch once you are in, on every route and every endpoint, including the ones with no visible button.
Because the login screen exists, the app feels secure. Nobody clicks “sign in” and then manually types /dashboard in a logged-out tab to check. But that is the first thing a scanner does, and eventually the first thing someone less friendly does too. This is the same shape as most of what we find in AI-generated code: the insecure version works, so it ships.
How to check your own
You do not have to wonder which side of this your app is on. Paste your app's URL into the scanner: it runs the same anonymous, read-only checks and tells you exactly what a logged-out visitor can reach, which routes serve a private view, which endpoints answer without a token, and whether your database is readable, instead of leaving you to guess. If it finds an open surface, it gives you the specific fix.
Frequently asked questions
Isn't having a login page enough?
No, and this is the exact trap. A login page proves the app can authenticate you, that is, confirm who you are. It says nothing about authorization, which is the separate check that runs after login to decide whether this visitor is allowed to see this data. AI builders reliably wire up the login screen and skip the per-route and per-endpoint authorization check, so the door has a lock on the front and nothing on the back.
How did you check without hacking anything?
Every probe was read-only and unauthenticated, exactly what any anonymous visitor's browser already does. We requested each app's own pages and endpoints with no login and flagged an app only when it returned a private page or real records. We never wrote data, never guessed a password, and never used anything a normal browser cannot. If our scan can see it, so can anyone.
What is the difference between an open page and an open API?
An open page renders its logged-in view to a logged-out browser: it looks bad and may leak whatever is on screen, but the data still flows through the app. An open API or open database returns the underlying records directly to an anonymous request, which is worse, because a stranger with browser dev tools can read the raw data with no account at all. Of the 124 exposures, 35 were the second kind.
How do I check my own app?
Paste your app's URL into Prbl's scanner. It runs the same anonymous, read-only checks in about thirty seconds and tells you exactly what a logged-out visitor can reach: which routes serve a private view, which endpoints answer without a token, and whether your database is readable. Then it gives you the specific fix for each.
Check your app in seconds
If your app was built with an AI tool and has any kind of login, this is one of the most valuable things to verify before anything else. A scan reads what your app serves and checks whether the door is actually locked. Run a free scan and find out which side of this your app is on.