BOLA vs. BFLA: the two API authorization failures that matter most
TrekShield Security Team · March 20, 2026 · 7 min read
The two most impactful classes of API vulnerability sound almost identical and are constantly confused: BOLA (Broken Object-Level Authorization) and BFLA (Broken Function-Level Authorization). They sit at the top of the OWASP API Security Top 10 because they’re common, high-impact, and invisible to automated tooling. Understanding the difference is the first step to testing for both.
BOLA: can you access this specific object?
BOLA — often called IDOR — is about which records you can reach. The API checks that you’re logged in, but not that the object you’re requesting belongs to you.
GET /api/orders/10432 -> your order (fine)
GET /api/orders/10433 -> someone else's order (BOLA)
Same endpoint, same permission level, different object. The function is one you’re allowed to call; the instance isn’t yours. In a multi-tenant product this is catastrophic — it can mean one customer reading another’s data at scale via enumeration.
BFLA: can you call this operation at all?
BFLA is about which actions you can perform. The API fails to check that your role is allowed to invoke a function — typically a privileged or administrative one.
DELETE /api/users/8821 (should be admin-only)
POST /api/admin/refunds (should be finance-only)
Here the problem isn’t the object — it’s that a regular user can reach an operation reserved for a higher privilege level. BFLA often hides in “hidden” admin endpoints that the UI never exposes but the API happily serves.
The one-line distinction
- BOLA = right function, wrong object (horizontal — another user’s data).
- BFLA = wrong function for your role (vertical — an action above your privilege).
Both are authorization failures. BOLA crosses a data boundary; BFLA crosses a privilege boundary.
Why automated tools miss both
Neither has a signature. A 200 OK returning another tenant’s order looks identical to a legitimate one. A successful admin call from a normal user looks like any other success. Detecting these requires knowing who the caller is and what they should be allowed to touch or do — semantic context a scanner doesn’t have. That’s why they need a human with multiple accounts.
How we test for each
For BOLA:
- Provision two isolated accounts (ideally two tenants).
- As Account A, replay requests substituting Account B’s object identifiers — in the path, query, body, and nested references.
- Test every verb: read is the start, but
PUT/PATCH/DELETEon another’s object are often worse. - Prove impact with the exact cross-account request/response pair.
For BFLA:
- Enumerate every function, including undocumented and admin-adjacent endpoints.
- As a low-privileged account, attempt privileged operations directly against the API.
- Try method and role tampering —
GETvsPOST, forced browsing to admin routes. - Confirm the unauthorized action actually took effect, not just returned a success code.
How to defend
- Enforce authorization at the data and function layer, derived from the authenticated session — never from client-supplied identifiers or hidden UI.
- Centralize authorization in one well-tested policy layer instead of per-endpoint checks that drift.
- Deny by default for every function; require an explicit allow for each role.
- Add regression tests asserting that Account A can’t touch Account B’s objects (BOLA) and that low-privilege roles can’t call privileged functions (BFLA).
The takeaway
BOLA and BFLA are the quiet giants of API security: easy to introduce, invisible to scanners, and devastating when exploited. Testing for them takes multiple accounts, a methodical eye, and the discipline to prove impact — which is exactly how every API we touch gets tested.
Want proof your tenants are actually isolated?
A short scoping call, no obligation.