IDOR — the older term
Insecure Direct Object Reference: an endpoint exposes an internal identifier (/files/42) and trusts the client to only request files they own. Swap the ID, get someone else's file.
Fix: validate ownership server-side on every request.
BOLA — the API-Top-10 framing
Broken Object-Level Authorization: same root cause, but the framing emphasises that this isn't about the identifier being predictable — it's about the authorization check being missing.
A UUID-based reference (/files/9f8a-3c2b-...) is still BOLA-vulnerable if the server doesn't check ownership. Hard-to-guess IDs are not a fix; they're security through obscurity.
Why this matters
We regularly see teams switch from auto-increment IDs to UUIDs and conclude they've fixed IDOR. They haven't. The auth check is still missing — they've just made it harder to enumerate.
How we test
Authenticated as user A, capture a request that fetches their data. Replay the request from user B's session, swap A's resource IDs in. If the response succeeds, BOLA confirmed.
The fix
Every resource access query has an ownership predicate. In Laravel terms:
$order = Order::where('id', $id)
->where('user_id', auth()->id())
->firstOrFail();
Not:
$order = Order::findOrFail($id); // BOLA waiting to happen
And not in the controller; in the query. Defence in depth means even if the controller is wrong, the model can't return data the user doesn't own.