Design Partner ProgramNow accepting initial enterprise design partners.
APPSEC HAYROK · BUMBLEBEE · 018

Authorization Is a Runtime Property.

Why static AuthZ reviews miss the interesting bugs — and what it takes to prove an authorization check actually scopes access, object by object, identity by identity, on this build.

DA
Dan Aoki · Hayrok's Bumblebee
Practical guidance for evidence-driven security validation
Aug 13, 202611 min readAppSec
Key takeaways
Invisible

Static reviews miss BOLA because the logic looks correct in code.

Runtime

Authorization is verifiable only by exercising request paths with real credentials.

Systematic

Real validation means cross-tenant object access and state-dependent checks.

At scale

Autonomous validation supplies the scale and evidence microservices demand.

Here is an uncomfortable fact for anyone who has shipped a static authorization review as a compliance checkbox: the most dangerous AuthZ bugs are invisible in the code.

Broken Object Level Authorization has topped the OWASP API Security list for good reason. And BOLA is, almost by definition, a bug a code review will not find.


The invisible nature of authorization bugs

The authorization logic is correct. The @RequireRole decorator is present. The middleware checks a session. Everything a static reviewer looks at passes.

STATIC REVIEW · PASS 3 / 3 checks
✓Authorization logic present and correct on the handler
✓@RequireRole decorator applied to the route
✓Middleware validates the session on every request
THE GAP “this endpoint checks that a user is authenticated” → “this endpoint checks that this user is authorized to access this object”

That gap only becomes observable when you actually call the endpoint with the wrong user's token against the right object's ID.


Structural limitations of code reviews

Static review answers
Does an authorization check exist on this path?

A binary, structural question about the shape of the code — answerable by reading it.

It cannot answer
Does that check scope access to the correct resource — for every object type, across every relationship, including last sprint's migration?

A behavioral question about a running system. Only a real request can settle it.

Modern applications have hundreds of object relationships. A single missed scope check on any one of them, on any one endpoint, is a BOLA vulnerability.

users→ orgs→ projects→ documents→ comments EVERY EDGE NEEDS A SCOPE CHECK

Multiply that across a microservices architecture with dozens of services, each implementing its own authorization logic slightly differently, and you get a surface area no manual review realistically covers. This is why authorization is fundamentally a runtime property: it can only be verified by exercising the actual request path with real credentials against real objects, and observing the real response.


The mechanics of runtime authorization testing

Effective validation means systematically attempting the thing a code reviewer cannot: cross-tenant object access. For every discoverable object ID and every authenticated identity — does the API return data it should not?

01

Cross-tenant object access

Enumerate discoverable object IDs and replay them against every authenticated identity. The only acceptable result is a denial.

02

Privilege boundary testing

Can a lower-privileged role reach an endpoint or field gated to a higher-privileged one, through a parameter the client controls?

03

Vertical and horizontal escalation

Not just “can User A see User B's data,” but “can Org A's service account act on Org B's resources through an indirect object reference.”

04

State-dependent authorization

Checks that pass at object creation but are never re-evaluated after an ownership transfer, a role change, or a subscription downgrade.

Doing this manually — endpoint by endpoint, object by object, across every release — is not something a human appsec team can sustain at the velocity modern engineering ships.

Hayrok · runtime authorization validation

Hayrok continuously maps API surfaces, generates realistic multi-tenant test identities, and safely attempts authorization bypasses against your running application — producing validated proof of a specific bypass, not a generic “review authorization logic” recommendation.


From findings to actionable evidence

The output that moves an engineering team is not “endpoint X might have an AuthZ issue.” It is this:

HTTP CAPTURE · /api/invoices/{id} VALIDATED · HIGH
// identity: account_A session token · target: account_B object GET /api/invoices/4471 HTTP/1.1 Authorization: Bearer <session_account_A> 200 OK { "invoice_id": 4471, "account": "account_B", "total": "$12,480.00", "billing_email": "ap@acme.io" } // object ownership check missing at // services/billing/handlers/invoice.py:88
EVIDENCE request · response · missing-check location · safe reproduction steps

Using Account A's session token, we retrieved Account B's invoice by incrementing the ID. Here is the request, here is the response, and here is the exact line where the ownership check is missing. That is a bug an engineer fixes in an afternoon, because there is no ambiguity about whether it is real.


Validating behavior over intent

Appsec programs that still gate authorization assurance on a point-in-time code review are validating the wrong artifact. Code review confirms intent. Runtime validation confirms behavior — and behavior is what an attacker actually interacts with.

DimensionStatic AuthZ reviewRuntime validation
Artifact validatedThe code as written — intent.The running application — behavior.
Question answeredDoes a check exist on this path?Does the check scope access to the correct object, for this identity?
BOLA coverageStructurally blind: correct-looking logic passes.Every object relationship exercised with real credentials.
Output“Review authorization logic on endpoint X.”Request, response, and the missing check's exact location.
CadencePoint-in-time, at design or audit time.Continuous — run against every release.

Continuous, evidence-driven validation — run against every release rather than once at design time — is what closes the gap between “we reviewed the AuthZ logic” and “we proved the AuthZ logic holds, this week, against this build.”

Ship the review. Then validate the runtime. The second one is where the real bugs live.

Glossary of terms

BOLA

Broken Object Level Authorization — an endpoint authenticates the caller but fails to confirm the caller owns the specific object requested.

Indirect object reference

A client-supplied identifier that resolves to a resource on the server, allowing access to be steered by changing a parameter.

Cross-tenant testing

Replaying requests for one tenant's objects using another tenant's credentials to confirm isolation holds.

Horizontal escalation

Reaching a peer identity's data at the same privilege level — User A retrieving User B's records.

Vertical escalation

Reaching an endpoint, field, or action gated to a higher-privileged role than the one held.

State-dependent authorization

Access decisions that must be re-evaluated after ownership transfers, role changes, or plan downgrades — and often are not.

Runtime property

A behavior only observable while the system runs, and therefore unverifiable by reading source alone.

PROVE THE AUTHZ LOGIC HOLDS — THIS WEEK, THIS BUILD

Validate authorization against your running application.

Hayrok maps API surfaces, generates multi-tenant test identities, and safely attempts object-, function-, and tenant-level bypasses — returning validated proof with the request, the response, and the missing check.

DA
About the author

Dan Aoki · Hayrok's Bumblebee

Practical guidance for evidence-driven security validation. Field notes from the hive.

KEEP READING