IDOR, Drawn: The Branch That Is Not There (Diagram)

Change 1043 to 1044 in the address bar and press enter. If you get somebody else's invoice back, with a completely normal 200 OK, that is an IDOR, and it is the single most common serious bug we find in apps built with AI coding tools.

What makes it hard to spot in a code review is that there's nothing wrong on the screen. The code does exactly what it says. The problem is a line that was never written.

A flowchart of an IDOR bug. A request for invoice 1043 has its id read straight from the URL into a query that filters on id alone, which returns another customer's invoice with a 200 OK. A dotted branch shows the ownership condition that was never written, which would have answered 404 for a row belonging to someone else.
Nothing here is wrong. Something here is absent.Full explanationMermaid source

Why do AI coding tools produce IDOR bugs so reliably?

Because you asked for a feature, and authorization isn't a feature. A prompt like "let users view their invoices" describes the happy path, so the model writes the happy path: find the row, send it back. Nobody wrote down the part where the app refuses. The generated code isn't broken, it's incomplete in a way that runs perfectly in testing.

How do I test my own app for IDOR in one minute?

Sign in as one user, open any page whose URL contains a numeric id, and change the number by one. If you see another account's data, you have an IDOR. Do it again with a second account so you're certain you aren't just looking at your own second record.

Should the app return 404 or 403 when the row belongs to someone else?

404, in nearly every case. A 403 confirms the record exists, which tells an attacker enumerating ids exactly which ones are real. Answering 404 for both "no such row" and "not your row" gives away nothing.

Do random UUIDs fix IDOR?

No. They make guessing harder, not impossible, and they do nothing once an id leaks through a shared link, a referrer header, an export, or a support ticket. Unguessable identifiers are a speed bump. The ownership condition is the fix.

::

Is the Condition There on Every Route?

CheckYourVibe probes your deployed API with ids that belong to somebody else and reports the routes that answer with data.

diagrams

IDOR, Drawn: The Branch That Is Not There (Diagram)