Blog · API Security

BOLA vs BFLA: the API authorization flaws scanners miss

Authorization, not injection, is what breaks most modern APIs. The two flaw classes that do the damage — BOLA and BFLA — are invisible to a scanner, because a scanner has no concept of who should be allowed to do what. Here is the difference between them, why pattern matching cannot find either, and how to actually test for both.

Planck Defense · Offensive Security Team · August 28, 2026 · 7 min read

Look at almost any serious API breach of the last few years and you will find the same root cause: not a clever injection payload, but a missing authorization check. Someone requested an object that was not theirs, or called a function they should never have reached, and the server handed it over. These are the two classes at the top of the OWASP API Security Top 10 — BOLA at number one and BFLA at number five — and together they account for the majority of real-world API compromise.

They are also the flaws your scanner will never report. Understanding why starts with knowing exactly what each one is.

What is BOLA (Broken Object Level Authorization)?

BOLA is a failure to check that the user asking for an object is allowed to have that specific object. APIs expose objects by identifier — /orders/124, /users/89/profile, /documents/abc-123 — and the vulnerability is simple: the endpoint authenticates you (it knows you are a logged-in user) but never verifies that order 124 belongs to you before returning it.

So an attacker logs in with their own account, sees a request for GET /orders/124, and simply changes the number: GET /orders/125, 126, 127. If the server returns each one, they can walk the entire order table — other customers' addresses, amounts, and items — without ever touching an admin function. If you have heard this called IDOR (insecure direct object reference), it is the same bug; OWASP renamed it BOLA for the API context. Identifiers do not have to be sequential integers, either. UUIDs assumed to be unguessable, references buried in a request body, and IDs resolved through nested GraphQL fields are all BOLA surface.

What is BFLA (Broken Function Level Authorization)?

BFLA is a failure to check that the user is allowed to perform that action at all. Where BOLA is about data you should not see, BFLA is about functions you should not be able to call. A standard user finds the admin routes — DELETE /users/89, POST /admin/refunds, PUT /accounts/settings/global — and simply calls them with their ordinary session token. If the server executes the request because it only checked that you are logged in, not which role you hold, that is BFLA.

It often hides behind the client. The admin button is not rendered in your UI, so the assumption is that you cannot reach the function — but the API endpoint is still live, and nothing stops you from calling it directly. Switching an HTTP method on the same path (GET to DELETE), guessing an undocumented admin route, or invoking a gRPC service method the client was never meant to expose are all ways BFLA shows up.

BOLA vs BFLA: the difference in one line

The quickest way to keep them straight: BOLA crosses between accounts at the same level; BFLA crosses between levels. BOLA is a regular user reaching another regular user's data. BFLA is a regular user reaching an administrator's powers.

DimensionBOLABFLA
OWASP API rankAPI1 (2023)API5 (2023)
What failsObject ownership checkRole / privilege check
Attacker gainsAnother user's dataA function above their role
Boundary crossedBetween peer accountsBetween privilege levels
Classic exampleGET /orders/{other_id}DELETE /users/{id} as a normal user
Also known asIDORPrivilege escalation, forced browsing
How to catch itReplay one account's request as anotherReplay a low-privilege token against privileged routes

Some findings are both at once: an endpoint that is both admin-only and object-scoped can fail on either axis, which is why real testing checks each dimension separately on every operation.

Why scanners miss both

A vulnerability scanner or DAST tool works by firing payloads at inputs and matching responses against a library of signatures. That model is fundamentally blind to authorization, for one reason: authorization is relative. There is nothing wrong with the response to GET /orders/124 in isolation — it is a perfectly valid 200 with a valid order. Whether it is a vulnerability depends entirely on who asked. A scanner sees one request, one response, one identity. It cannot express the question that defines BOLA and BFLA: “should this user be allowed to do this?”

To answer that, you need at least two accounts and a way to compare them — to take a request that is legitimate for user A and replay it as user B, then check whether the server wrongly allows it. That is a stateful, identity-aware, multi-account exercise. It is exactly the shape of testing a signature engine cannot do, which is why these flaws sail straight through automated scans and land in production.

How to actually test for BOLA and BFLA

The method is conceptually simple and mechanically demanding. You authenticate as two or more user types — at minimum two peer accounts (for BOLA) and one low-privilege plus one high-privilege account (for BFLA). Then, for every operation the API exposes:

  • For BOLA: take every request that references an object — in the path, a query parameter, or the body — and replay it with the other account's session, substituting object identifiers across accounts and tenants. If account B receives account A's object, that is a confirmed BOLA.
  • For BFLA: take every privileged or admin function and call it with the low-privilege token, including method swaps on the same path and routes that are not exposed in the UI. If the action executes, that is a confirmed BFLA.

Doing this by hand across a real API — dozens or hundreds of operations, each with multiple parameters, times several role pairings — is enormous, repetitive work, which is why it so often gets sampled rather than done completely. This is where an agentic API penetration test fits the problem exactly. You provide one bearer token per user type; the agent parses your OpenAPI spec, enumerates every operation, and replays one role's requests as another across the whole surface. Because it is an agentic pentester rather than a scanner, it does not stop at “this looks off” — it confirms the cross-account access actually happened and reports it with the exact request and response that prove it, rated with a CVSS v3.1 vector.

Authorization is the part of API security that pattern matching cannot reach and that manual testing rarely covers exhaustively. Testing it well means treating every endpoint as a question about identity, and answering that question with more than one account. Anything less leaves the most common path into your data untested.

Live

Watch the agent replay one role as another

This is the Operator console running exactly the test described above: cross-account BOLA on object identifiers, then BFLA on admin-only functions called with a low-privilege token. Illustrative demo against api.example.com — the requests, sessions, and confirmations are what a real run streams.

FAQ

Common questions

What is the difference between BOLA and BFLA?

BOLA (broken object level authorization) is about data: a user accesses another user's object, such as requesting GET /orders/124 when order 124 belongs to someone else. BFLA (broken function level authorization) is about actions: a user invokes a function or role they should not reach, such as a standard user calling an admin-only endpoint. BOLA crosses the boundary between accounts at the same privilege level; BFLA crosses the boundary between privilege levels.

Is IDOR the same as BOLA?

Largely yes. IDOR (insecure direct object reference) is the older name for the same class of bug. OWASP formalized it as BOLA, the number one risk in the API Security Top 10. BOLA is the term used for APIs, where object identifiers in the URL path or request body are the most common way the flaw appears.

Why can't vulnerability scanners find BOLA and BFLA?

A scanner tests one request at a time against a signature and has no concept of identity or roles. BOLA and BFLA are only visible when you compare what one user can do against what another user should be allowed to do, which requires at least two authenticated accounts and replaying one role's requests as another. Pattern matching cannot express that.

How do you test an API for BOLA and BFLA?

You authenticate as two or more user types, then for every endpoint that accepts an object identifier or exposes a privileged function, you replay one role's request as another and check whether the response leaks data or performs the action. An agentic pentester does this across every documented operation and reproduces each finding with the exact cross-account request and response.

Keep Reading

Related

Get Started

Test what your API actually authorizes

Give Operator your spec and a token per role. It will replay one role as another across every operation, and prove what it finds.