Broken object-level authorization () is the number-one risk in the OWASP API Security Top 10, and in a microservices estate it is also the easiest class to miss. The reason is structural: the failure only appears when two different roles interact with the same object. A scanner sitting inside a single authenticated session cannot see the bug, because that session is — by definition — authorised to see its own data.
This post explains why microservices amplify risk, why single-session testing misses it, and how multi-role replay surfaces it deterministically at scale.
What is (and how it differs from )#
is the failure to enforce that the caller is allowed to act on the specific object they reference. A request like GET /api/v2/invoices/9182 is authenticated, but the server never checks that invoice 9182 belongs to the calling tenant.
People often use and interchangeably. The practical distinction is scope: (insecure direct object reference) is the broad web-app term for object references an attacker can tamper with; is the API-specific authorization failure that OWASP formalised. We unpack the nuance in IDOR vs BOLA. For testing purposes, the detection technique is the same.
Why microservices make worse#
Three properties of a microservices architecture multiply the risk:
- Authorization is distributed. The gateway authenticates the caller, but each service decides object ownership independently. One service that trusts an upstream
X-Tenant-Idheader without re-validating it is enough. - Internal endpoints leak outward. Service-to-service routes that assume a trusted network sometimes become reachable through a misconfigured gateway, with no tenant scoping at all.
- List and aggregate endpoints fan out. A reporting service that joins across tenants for an admin view will happily return the join to a lower-privileged caller if the scope filter is missing.
Why single-session scanners miss it#
A traditional DAST tool crawls and fuzzes inside one session. Within that session every authorised response is a 200, so there is nothing anomalous to flag. The bug is relational: it exists in the gap between what role A may see and what role B actually receives. You cannot detect a relationship by observing one side of it.
The multi-role replay technique#
Pentrova’s Authorization Matrix is built specifically for this class. The method is three steps:
- Establish every role. A persistent authenticated session is created for each role the target exposes — tenant-admin, tenant-member, and a cross-tenant stranger at minimum — storing cookies, bearer tokens, certs, and refresh grants so every request is correctly authenticated.
- Capture reference responses. Pentrova walks the protected endpoints under one role (typically the highest-privilege role with legitimate access) and records the reference response per endpoint. That is the ground truth: what the endpoint returns to an authorised caller.
- Replay under every other role. The exact request is replayed under every other role and diffed against the reference, with a normalisation pass that ignores headers, timestamps, and trace IDs. If role B receives data only role A should have seen, Pentrova emits a finding with the request, both responses, and the specific fields that leaked.
# Reference response captured as tenant-admin (authorised)
GET /api/v2/invoices/9182 → 200 { "id": 9182, "tenant": "acme", "total": 4200 }
# Same request replayed as a cross-tenant member (should be 403)
GET /api/v2/invoices/9182 → 200 { "id": 9182, "tenant": "acme", "total": 4200 }
# ^ cross-tenant leak → BOLA finding
The technique does not depend on knowing what the bug looks like in advance. It depends on the relationship between roles — which is exactly what makes it the right tool for .
Where the interesting bugs hide#
List endpoints and aggregate dashboards are the usual suspects. A list endpoint that forgets to scope by tenant returns every object the database can reach when an admin issues the request — and the member replaying the same request gets the full list too. Aggregate dashboards are the same pattern one level up: the sums and counts leak cross-tenant visibility even when the individual records appear filtered.
Key takeaways#
- is a relational failure: it only shows up when two roles touch the same object, so single-session scanners are blind to it.
- Microservices amplify the risk through distributed authorization, internal endpoints, and cross-tenant aggregate queries.
- Multi-role replay — establish roles, capture references, replay and diff — is the reliable way to surface it.
- The fix-ready evidence is a tight diff: the request, both responses, and the leaked fields.
FAQ#
How many roles should I configure to test for ? At least three: a privileged role, a same-tenant lower-privileged role, and a cross-tenant stranger. Multi-tenant platforms should add a second tenant so cross-tenant reads are exercised directly.
Is testing safe to run against production? The replay technique is read-dominant and runs under sandbox guardrails with destructive actions held back. The recommended pattern is full coverage against staging and conservative runs against production.
What does a fix usually look like? An object-ownership check at the service boundary — verify the authenticated principal owns or is scoped to the referenced object before returning it. The evidence bundle makes the fix a tight diff rather than a refactor.
Want to see multi-role replay against your own API? Start a free engagement or read how API Pentesting wires in your auth modes.