Articles / BOLA: The API Flaw That Tops the OWASP List
OWASP API1 · BOLA

BOLA: The API Flaw That Tops the OWASP List

Change the number in the URL, get someone else's data. That one sentence describes Broken Object Level Authorization, the vulnerability OWASP ranks first among API risks — not because it is clever, but because it is everywhere. BOLA is the API era's answer to the insecure direct object reference, and it hides in code that looks entirely correct.

An API endpoint like GET /api/invoices/4412 looks harmless. The server authenticates the caller — they are a valid, logged-in user — and returns invoice 4412. The bug is what the server didn't do: check whether this particular user is allowed to see that particular invoice. Authentication asks "who are you?"; authorization asks "are you allowed to touch this object?" BOLA is what happens when an API answers the first question and forgets the second.

The attack is often this simpleGET /api/invoices/4412 → 200 OK (my invoice)
GET /api/invoices/4413 → 200 OK (someone else's invoice)
id lookupClientGET /invoices/4412Authenticationvalid session?Object authorizationdoes caller own it?Databasefetch the recordResponsereturns the objectAttacker justincrements the idOwnership checkmissing → returnsanother user'sobject
An authenticated request still needs a per-object ownership check.

Why it is so common

Object IDs are exposed everywhere in a modern API — in paths, query strings, request bodies, and headers. Every one of them is a place where the server must re-verify ownership, and it only takes one endpoint that trusts the ID to open the door. Sequential integer IDs make exploitation trivial, but even random UUIDs do not fix the underlying flaw; they only make it harder to guess, not harder to abuse once an ID leaks.

Why it's API1: BOLA leads the list because it is both the most prevalent API vulnerability and among the most impactful: a single missing check can expose every record of a given type across every tenant.

Fixing it properly

  • Enforce authorization at the object level, server-side, on every request. For each object the request touches, verify the authenticated principal is entitled to it. Never rely on the client only requesting IDs it owns.
  • Centralise the check. A shared authorization layer or middleware that every handler must pass through is far safer than per-endpoint checks a developer can forget.
  • Prefer deriving scope from the session. Where possible, list objects by the authenticated user (WHERE owner_id = :me) rather than accepting an arbitrary ID and checking afterward.
  • Test for it continuously. Automated tests that replay one user's requests with another user's token catch BOLA before shipping; unauthorised-access attempts should be logged and alerted on.
  • Do not treat unguessable IDs as a control. UUIDs reduce enumeration but are not authorization.

BOLA is a discipline problem more than a technical one: the fix is a check that must be present on every object access, forever, with no exceptions. That is exactly the kind of invariant that erodes as an API grows — which is why inventorying your endpoints and testing authorization on each is not a one-time task but a standing one.

Test for it — in practice
  • As user A, request one of your own objects (e.g. GET /api/invoices/{id}); then replay the same request as user B for user A's id and watch the response code. A 200 instead of 403 is BOLA.
  • Walk a handful of sequential ids on an object endpoint and see whether records you don't own come back.

Systematically testing object-level authorization across every endpoint and role is what our assessment and SecStudio agents automate.

Keep reading
BFLA: When Users Reach Admin Functions