A crashed security check let everyone in
In this controlled demo, the permission check times out and the app treats the error as "allowed", so a regular member opens a managers-only salary page.
Demo built and tested 20 Sept 2026 · Published 28 Sept 2026 · Last reviewed 28 Sept 2026 · By Ctrl+Z Therapy (how we test)
Can an error in a permission check let everyone in?
Yes, if the code treats an error as "allowed". When the permission check crashes or times out, a catch block that returns true opens the door exactly when something is already wrong. In our controlled demo (a fake HR app), a timeout let a regular member open the managers-only salary page. The fix is to fail closed: no confirmation, no access.
How to tell if your app has this
No code needed.
- Ask your AI tool: "In my permission and login checks, what happens if the check throws an error or times out? Show me every catch block."
- Look for catch blocks that return true, "allowed" or a default role. They should deny access instead.
- In a test environment, make the permission service fail (for example, point it to a wrong address) and open a protected page. You should see an error, not the page.
Before and after
The check timed out. The page opened anyway.
No confirmation, no access. Managers still get in.
Why AI-built apps end up with this
AI tools add try/catch so the app doesn't crash, and the quickest way to "handle" an error is to return a default. If that default is "allowed", every normal test passes, because the permission service almost never fails while you build.
How do I fix it? Paste this into your AI tool
My app's permission checks catch errors (like a timeout) and return "allowed". Change every authorization check so that if the check fails or can't be completed, access is denied (fail closed) and the user sees a safe, friendly error. Only a confirmed "allowed" result should grant access. Log the error for us, but never show internal details to the user. Then add a test where the permission service times out and access is denied, and one where a confirmed user still gets in.Works with Lovable, Bolt, Cursor, Replit and similar tools. Then run the check-up below on your own app.
How we checked the fix
| Same request | Before | After |
|---|---|---|
| Permission check times out | Access allowed | Access denied |
| Permission confirmed | Access allowed | Access allowed |
Results from our demo test, run against the same demo before and after the fix.
Common mistakes when fixing this
- Catching the error is fine. Returning "allowed" from the catch block is the bug.
- Retrying is fine too, but if every retry fails, the answer is still no.
Questions people ask
Isn't denying access during an outage bad for users?
A short "try again" message is much cheaper than showing private data to the wrong person. Show a friendly error, retry in the background if you like, and log the failure so you notice it.
Does every error need to fail closed?
Every security decision does: who can see, change or pay for something. For harmless features, like a recommendation box, falling back to a default is fine.
Where does this usually hide?
In middleware or helper functions that wrap the permission check, in feature flags used as permissions, and in code that calls an outside auth or permission service.
For developers: the cause and the fix in code
− except TimeoutError: − return True + except TimeoutError: + return False # fail closed
Simplified. Your stack will look different; the principle is the same.