Vulnerability

Broken Object Level Authorization (BOLA)
detect, understand, remediate

BOLA is the API-context authorization failure where an endpoint accepts an object identifier and returns the resource without verifying that the caller is allowed to read or modify that specific object. Ranked first on the OWASP API Security Top 10 (API1:2023), BOLA is the most common API vulnerability and the most damaging when it leaks tenant data.

No credit card required. Free plan available forever.

Severity

High

CWE ID

CWE-639

OWASP Top 10

API1:2023 – Broken Object Level Authorization

CVSS 3.1 Score

8.1

What is broken object level authorization (BOLA)?

Broken object level authorization (BOLA) is an API authorization flaw in which an endpoint accepts an object identifier in the URL, query string, header, or request body and returns or modifies the referenced object without verifying that the authenticated caller is allowed to access that specific object. Authentication passes, the request reaches the handler, and the handler reads from the database using the supplied identifier. The authorization check that should sit between those two steps is missing or only partially enforced.

OWASP ranks BOLA first on the API Security Top 10 (API1:2023). It is consistently the most common, the most exploitable, and the most damaging API vulnerability across bug bounty submissions, public disclosures, and production penetration tests. It usually leaks data across the strongest trust boundary in a SaaS application: the boundary between two tenants.

BOLA is closely related to IDOR but the two are not interchangeable. IDOR is the broader web-application pattern where any object reference is exposed without authorization (cookies, file paths, sequential numeric IDs in form posts). BOLA is the narrower API-context manifestation: a REST, GraphQL, or RPC endpoint that takes an object ID and returns the object without an ownership or tenancy check. Most modern multi-tenant SaaS applications expose far more API surface than HTML surface, which is why OWASP separated BOLA out as its own API Top 10 category.

BOLA vs IDOR: where the line sits

DimensionIDORBOLA
SurfaceWeb pages, forms, file paths, any HTTP-exposed object reference.REST, GraphQL, RPC, and mobile API endpoints.
CatalogOWASP Top 10 A01:2021 (Broken Access Control), CWE-639.OWASP API Security Top 10 API1:2023, CWE-639 / CWE-285.
Typical impactReading another user's record, accessing another user's file.Cross-tenant data exposure, mass extraction by automated enumeration, privilege escalation through API.
Fix locationPage handler authorization check.API gateway and per-endpoint policy, plus tenant-scoped database queries.

How it works

1

Authenticate as a real tenant

The attacker signs up as a legitimate user of the SaaS application. They authenticate, capture a valid access token, and inspect their own API traffic to learn the route shapes.

2

Enumerate object identifiers

They pull object IDs from their own API responses (account IDs, invoice IDs, document IDs) and observe the structure: incrementing integers, ULIDs, or UUIDs that leak ordering through the embedded timestamp.

3

Replay across the tenant boundary

They replay GET, PUT, and DELETE calls with their own auth token but with another tenant's object ID. If the endpoint resolves the object without checking ownership or tenancy, the API responds with the cross-tenant data.

4

Automate at scale

A simple script iterates the ID space and exfiltrates objects across thousands of tenants. The fact that the request authenticated cleanly is exactly what makes BOLA invisible to most authentication-only monitoring rules.

Common causes

Lookup by primary key without tenant scoping

The handler runs SELECT * FROM invoices WHERE id = $1 instead of SELECT * FROM invoices WHERE id = $1 AND tenant_id = $2. The first query trusts the ID; the second binds the tenant from the session.

Authorization at the gateway only

An API gateway authenticates the JWT and confirms the user has the invoice:read scope, then forwards the request. The downstream service assumes the gateway has done all the authorization work and does not re-check object ownership.

Implicit tenancy from a header or cookie

The endpoint reads tenant context from a client-supplied header (X-Tenant-ID, X-Org-Slug) instead of the server-side session. Any caller can set the header to a different tenant value and inherit that tenant's scope.

GraphQL field-level resolvers without checks

The top-level GraphQL query checks authorization, but nested resolvers (invoice.lineItems, document.versions) load child objects by ID without re-checking that the child belongs to the parent's tenant.

Admin and bulk endpoints reused for tenants

Internal admin endpoints that accept any object ID get exposed to tenant traffic during a refactor. Tenants now hit /api/v2/objects/:id with no tenant scoping in place.

Trusting client-side filters in mobile apps

A mobile app fetches /api/users and filters the response client-side to show only the current user. The API actually returns every user; nothing prevents a researcher from calling the endpoint directly and dropping the filter.

How to detect it

Automated detection

  • SecPortal's authenticated scanner replays API calls captured from one tenant against another tenant's object IDs to surface cross-tenant authorization gaps.
  • Parameter tampering tests vary the ID portion of the path, the body, and identifying headers, and compare HTTP status, response shape, and response size against a baseline.
  • Code scanning surfaces handlers that resolve objects by primary key without a tenant or owner predicate in the same query, a signature that maps cleanly to the BOLA root cause.

Manual testing

  • Provision two tenants with two users each. Capture the API traffic for tenant A, then replay every request with tenant B's token and tenant A's object IDs.
  • Test write methods (POST, PUT, PATCH, DELETE) as carefully as read methods. BOLA is not just a data leak; a write-side BOLA can let one tenant edit or delete another tenant's objects.
  • Walk every nested resource path: /tenants/:id/users/:id, /projects/:id/files/:id. Each segment is a separate authorization decision and any one of them can be the broken link.
  • Inspect identifier predictability. Sequential integers make mass enumeration trivial; ULIDs and UUIDv7 leak creation order and can still allow targeted enumeration when the attacker knows an approximate timestamp.

How to fix it

Bind tenant context to the database query, not the route handler

Every query that resolves an object by ID should also constrain by tenant or owner in the same statement. Pull the tenant from the verified session, not from a client-supplied header. A query that reads "WHERE id = $1 AND tenant_id = $2" cannot return another tenant's row even if the handler forgets a higher-level check.

Centralise authorization in a policy layer

Move object authorization out of individual handlers and into a policy layer (an authorization library, a sidecar, or a database row-level security policy). Handlers call check(actor, action, object) and a single audited rule set decides. New endpoints inherit the rule set automatically rather than re-implementing checks.

Test BOLA in CI/CD across user and tenant boundaries

Add integration tests that authenticate as user B and attempt every endpoint with user A's object IDs. Assert a 403 or 404 response. Run the same suite across tenants. New endpoints that ship without authorization will fail the test rather than the next pentest.

Prefer non-enumerable identifiers for external IDs

Use UUIDv4 (or another non-time-leaking opaque identifier) for any object that is exposed in API URLs. This does not replace authorization; an attacker who has the ID can still abuse a missing check. It does raise the cost of mass enumeration and limits the blast radius if a single ID is leaked.

Log denied authorization attempts

Treat 403 responses on object endpoints as a signal worth alerting on. Repeated 403s from one principal across many object IDs is an enumeration pattern. Without this telemetry, BOLA exploitation is invisible until the data is on a public forum.

How to report a BOLA finding to a client

BOLA findings are some of the easiest to demonstrate (a single replayed request) and some of the hardest to remediate properly (because the fix sits in policy and data access patterns, not in input validation). A clean report keeps the proof tight and the remediation guidance specific.

  • Pin the finding to one concrete endpoint and one concrete cross-tenant or cross-user ID swap. The proof should be reproducible from the report alone.
  • Capture the full request and response for both the legitimate call and the unauthorized call so the difference is obvious.
  • Score the finding with a CVSS 3.1 vector that reflects the real impact: privileges required, scope, and confidentiality and integrity impact change with how broadly the missing check applies.
  • Distinguish between a single-endpoint BOLA and a systemic BOLA. A pattern that recurs across many endpoints is a single underlying authorization architecture finding, not many independent issues, and the report should say so.
  • Recommend a centralised policy fix rather than a per-endpoint patch where the pattern is systemic. A list of patched endpoints does not protect the next endpoint that gets shipped.

How SecPortal helps with BOLA findings

SecPortal is the engagement record where authenticated scanner output, manual pentest findings, and remediation tracking live on the same engagement. For BOLA specifically, the platform supports the workflow at three points.

  • The authenticated scanner replays API calls across user contexts and tenants and flags responses that should not have been served, surfacing object-level authorization gaps before manual triage starts.
  • Findings management lets you log a BOLA finding once with the CVSS 3.1 vector, the OWASP API1:2023 mapping, the request and response evidence, and the remediation guidance from a 300+ template library, then attach every recurring instance back to the same systemic finding rather than creating duplicate records.
  • The branded client portal gives the client engineering team the finding, the proof, and the remediation owner in one place. Retests pair to the original finding so the verification record is anchored to the original scope.

For the wider API testing context, see the API security testing checklist and the web application testing use case. For severity calibration on findings like BOLA, see the research on severity calibration for pentest findings. For the function-level and field-level siblings in the OWASP API authorisation trio, see BFLA and BOPLA.

Compliance impact

Catch BOLA before your customers do

SecPortal's authenticated scanner replays API requests across user contexts and tenants to surface object-level authorization gaps. Start scanning for free.

No credit card required. Free plan available forever.