BOLA Testing

BOLA testing

Broken object level authorization is the most damaging flaw class in production APIs, and the one scanners are structurally blind to. This page explains what BOLA is, how it is exploited, why automated tools miss it, and how Planck Operator proves cross-account access across every object-scoped operation with reproducible evidence.

Definition

What BOLA is

Broken object level authorization, listed as API1:2023 in the OWASP API Security Top 10 and mapped to CWE-639, occurs when an API confirms that a caller is authenticated but never confirms that the specific object the caller references belongs to them. The server answers the question are you logged in, but skips the question is this yours.

The gap

Authentication without authorization

The token is valid, so the request is served. The object identifier in the path or body is never checked against the identity that presented the token, so any authenticated user can address any object.

Also called IDOR

The same flaw, API framing

BOLA is the API-specific name for what web testers long called an insecure direct object reference, or IDOR. Same root cause, same fix, described in the vocabulary of endpoints and objects.

Why it ranks first

Common, simple, high impact

Object identifiers travel in nearly every request an API serves, the exploit is a single substituted value, and the payoff is another user or tenant data. That combination puts it at the top of the list.

Exploitation

How BOLA is exploited

The attacker authenticates as a legitimate, low-value account, then tampers with the object identifier the API trusts. That identifier might be a sequential integer, a UUID assumed to be unguessable, an identifier nested inside a JSON body, or a value resolved through a GraphQL field. If the server does not bind the object to the caller, substituting another value returns data the attacker was never entitled to.

Impact scales with the operation. On a read, it is disclosure of another account records. On a write, update, or delete, it is silent modification or destruction of data the attacker does not own. In a multi-tenant system, a single working substitution can expose every tenant behind the same endpoint.

  • Sequential IDs incremented or decremented to walk neighboring records.
  • UUIDs harvested from other responses, logs, or referrers, then replayed.
  • Body-borne identifiers swapped inside create and update payloads.
  • Nested references reached through GraphQL fields and expanded relations.
  • Write operations, not just reads, targeted to modify or delete foreign objects.
The blind spot

Why scanners and DAST miss it

Detecting BOLA is not a payload problem, it is an authorization problem, and that is exactly what automated tooling cannot model.

No concept of ownership

A 200 looks like success

A scanner sees that an endpoint returns a valid response for a valid identifier and marks it healthy. It has no way to know that the identifier belongs to a different account, so a data breach is indistinguishable from correct behavior. There is no error, no anomaly, nothing a signature can match.

One identity is not enough

Detection needs a comparison

Proving BOLA requires at least two authenticated identities and a comparison of what each is permitted to reach. Fixed DAST scripts run as a single session against a single object graph, so the cross-account comparison that reveals the flaw never happens.

This is why BOLA is a defining case for API penetration testing that reasons about identity, and why it is a recurring theme in our writeup on BOLA versus BFLA authorization flaws.

How Operator tests it

Testing BOLA at full coverage

You provide one bearer token per role or tenant. Planck Operator reads the specification, enumerates every operation that accepts an object identifier, and builds an authorization matrix of who should reach what. It then replays one identity requests as another across that entire matrix and compares the responses.

Two accounts in the same role is often the strongest signal, because it proves horizontal access between peers rather than only vertical access between privilege levels. Because the agent works from the spec rather than a crawl, coverage is every object-scoped operation, not a sampled subset, and it reruns continuously so a BOLA introduced by a new deploy is caught the week it ships.

  • One token per role is all the access the test requires.
  • Every object-scoped operation enumerated from the spec, not sampled.
  • Cross-account replay of account A requests using account B identifiers.
  • Horizontal and vertical access both exercised across the matrix.
  • Continuous reruns so drift-introduced BOLA surfaces quickly.
Example

What a proven finding looks like

A simplified illustration using safe placeholder values. Account A is authenticated and requests an invoice object owned by account B.

GET https://api.example.com/v2/invoices/8842 HTTP/1.1
Host: api.example.com
Authorization: Bearer <account-A-token>

HTTP/1.1 200 OK
Content-Type: application/json
{ "id": 8842, "account_id": "B", "amount": 4120.00, "card_last4": "4242", "billing_email": "[email protected]" }

Account A never owned invoice 8842. The 200 response returns account B financial data, and the baseline request confirms the object belongs to B, not A. The finding ships with both request and response captures for both identities, so the cross-account access is reproducible and the fix is verifiable on retest.

Remediation

How to fix and prevent BOLA

The rule is simple to state and easy to omit: enforce object-level authorization on the server for every request that references an object, and never trust a client-supplied identifier as proof of ownership. Authorization must be checked against the authenticated identity at the point of data access, not assumed from an unguessable value.

  • Check ownership server-side on every object read, write, update, and delete.
  • Scope queries to the caller so the data layer cannot return foreign objects.
  • Do not rely on unguessable IDs as an access control; obscurity is not authorization.
  • Deny by default and grant access only when ownership or a role permits it.
  • Centralize the check so every new endpoint inherits it rather than reimplementing it.
FAQ

Common questions about BOLA

What is BOLA and why is it the number-one API risk?

BOLA, broken object level authorization, is listed as API1:2023 in the OWASP API Security Top 10. It happens when an API checks that a caller is authenticated but fails to check that the specific object being requested belongs to that caller. It ranks first because it is common, easy to exploit, and directly exposes other users and tenants data, and because object identifiers travel in almost every request an API serves.

Is BOLA the same as IDOR?

They describe the same underlying flaw. IDOR, insecure direct object reference, is the older web application term for tampering with an identifier to reach data you should not. BOLA is the API-specific name OWASP adopted for it. The fix is the same: enforce object-level authorization on the server for every request that references an object.

Why do scanners and DAST tools miss BOLA?

A scanner has no concept of who should be allowed to access which object. It can see that an endpoint returns 200 for a valid identifier, but it cannot know that the identifier belongs to a different account, so a correct-looking response is indistinguishable from a data breach. Detecting BOLA requires two authenticated identities and a comparison of what each is permitted to reach, which fixed scripts do not model.

What do you need from us to test for BOLA?

One bearer token per role or tenant is enough. Planck Operator uses the specification to enumerate every object-scoped operation, then replays one identity requests as another and compares the results. Two accounts in the same role is often the strongest test, because it proves horizontal access between peers rather than only vertical access between privilege levels.

How is a BOLA finding proven rather than just flagged?

Each finding ships with the full request and response evidence for both identities: the request made as account A referencing account B object, the successful response containing B data, and the baseline showing the object never belonged to A. That evidence is reproducible, so your engineers confirm and fix it on the first pass instead of triaging a maybe.

Get Started

Prove whether your API leaks across accounts

Give us one token per role and the agent will test every object-scoped operation for cross-account access, then hand you reproducible evidence. See also BFLA testing for function-level authorization.