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.

Technical name: Failing open on an authorization errorControlled demo · fake data

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.

  1. 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."
  2. Look for catch blocks that return true, "allowed" or a default role. They should deny access instead.
  3. 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

Before
Demo HR · signed in as sam (member)
Permission service timed out
Salariesmanagers only
Alice Demo$84,000
Bob Demo$91,500

The check timed out. The page opened anyway.

After
Demo HR · signed in as sam (member)
Access denied
We couldn't confirm your access. Try again in a moment.

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.

Fix it yourself

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 and after the fix
Same requestBeforeAfter
Permission check times outAccess allowedAccess denied
Permission confirmedAccess allowedAccess 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.

Learn more