Back to Field Notes
API & Application Security/Field Note

OWASP API Security Top 10 (2023) — Authorization Is the Whole Game

BOLA still wins. BOPLA arrived. Unrestricted Resource Consumption replaced the old 'Lack of Resources & Rate Limiting.' The list got more honest about where APIs actually break — and so should your test plan.

Author

Marco Pereira

Principal Application Security Engineer

Published

February 10, 2026

Read

13 min

Share
AI-generated illustration of a banking data center
AI-generated illustration of a banking data center
Key Takeaways
  • 01Six of the ten 2023 entries are authorization or auth-adjacent. APIs do not break because of cryptography or injection — they break because authorization is implemented in the wrong layer.
  • 02BOLA (API1) and BOPLA (API3) are different bugs with the same root cause: authorization is enforced on routes or actions, not on objects and their properties.
  • 03BOPLA is the failure mode that escapes UI-driven test plans entirely. Property-level enumeration must be in your contract test suite, not just your manual pentest.
  • 04API6 (Sensitive Business Flow abuse) is not a rate-limiting problem — it is a behavioral-detection problem. Treat it like fraud, not like DoS.
  • 05Improper Inventory Management (API9) is the silent killer. Most enterprises have 30–50% more APIs in production than their inventory shows; shadow and zombie APIs carry the most BOLA debt.

The 2023 revision of the OWASP API Security Top 10 is a meaningful improvement over the 2019 list. It accepts what every appsec engineer working with modern APIs already knew — broken authorization is the dominant API failure mode — and it adds Broken Object Property Level Authorization (BOPLA) as a distinct, frequently-missed risk.

This piece is the field-grade reading of the 2023 list. It is written for the appsec engineer who has to triage API vulnerabilities on Monday morning and the CISO who has to decide where to spend the next quarter's appsec budget.

The 2023 list — and where it actually breaks

/INSIGHT

Six of ten are authorization or its inventory prerequisite.

API1, API3, API5, API6, and API9 are direct authorization concerns or its prerequisite (you cannot authorize what you do not know exists). Add API10 for unsafe trust of upstream APIs and the score is six of ten. Treat 'API security' as 'API authorization' until proven otherwise.

/OWASP_API_2023

IDRiskRoot cause classField finding rate
API1BOLA — Broken Object Level AuthzAuthorizationFound in ~70% of pentests
API2Broken AuthenticationAuthenticationFound in ~30%
API3BOPLA — Broken Object Property Level AuthzAuthorizationFound in ~55%
API4Unrestricted Resource ConsumptionOperationalFound in ~40%
API5Broken Function Level AuthorizationAuthorizationFound in ~35%
API6Unrestricted Access to Sensitive Business FlowsBehavioral / fraudFound in ~25%
API7Server Side Request ForgeryInput validationFound in ~20%
API8Security MisconfigurationOperationalFound in ~50%
API9Improper Inventory ManagementDiscoveryUniversal — worst offenders
API10Unsafe Consumption of APIsTrust boundaryFound in ~30%

BOLA — and the test that always finds it

BOLA happens when an authenticated user can fetch or modify an object identified in the URL or body, simply by changing its identifier. The route is authenticated; the object is not authorized. Frameworks happily let this through because authorization is a programming pattern, not a default.

The reliable test: take any authenticated user A, replay every request, substitute the object ID with one belonging to user B, and check whether the API rejects. Run this in your contract tests, not just in your pentest.

/TEST · BOLA contract assertion

# Pseudocode for a contract test that fails CI on a BOLA regression.

import pytest
from clients import api_client

@pytest.mark.parametrize("path", ROUTES_WITH_OBJECT_ID)
def test_bola_isolation(path):
    user_a = api_client.login("user_a")
    user_b = api_client.login("user_b")

    obj_a  = user_a.create_object()
    obj_b  = user_b.create_object()

    # User A must NOT be able to read user B's object
    resp = user_a.get(path.format(id=obj_b.id))
    assert resp.status_code in (403, 404), (
        f"BOLA: {path} returned {resp.status_code} for cross-user fetch"
    )

    # And the response body must not leak it on a 404 either
    if resp.status_code == 404:
        assert obj_b.secret_field not in resp.text

BOPLA — the bug your UI tests will never find

BOPLA is the property-level cousin of BOLA. The route is authorized. The object lookup is authorized. But the response object contains a property — say, internal_credit_score, owner_email, or hidden_admin_note — that the requesting user is not entitled to see. The UI never displays it. The API returns it anyway.

BOPLA escapes UI-driven test plans entirely because the testing surface is the response payload, not the rendered screen. The fix is response shaping at the API layer based on the requesting identity. The test is automated property allow-listing per role.

/COMMON_FAILURE

Inputs are also a BOPLA surface.

BOPLA is symmetric: a write request that accepts properties the user is not entitled to set (mass assignment, e.g. setting role: 'admin' on a profile-update call) is the same bug. Test both response shaping AND request property whitelisting in CI.

API6 — the business-flow abuse that rate limits cannot solve

API6 — Unrestricted Access to Sensitive Business Flows — is the entry that most cleanly maps to a fraud problem rather than a security problem. Account creation at scale, coupon enumeration, content scraping, gift-card balance probing, login enumeration — all are abuses of legitimate flows by adversaries who do not need to break authentication.

Rate limiting alone does not solve it. The defenses are behavioral: device fingerprinting, network reputation, IP / ASN clustering, sequence analysis, and friction proportional to risk (CAPTCHA, step-up, hold-for-review). Treat the most-abused flows as fraud surfaces with their own KPIs.

  • 01Inventory the high-value flows: signup, login, password reset, coupon redemption, gift-card lookup, refund, balance check
  • 02Instrument per-flow KPIs: success rate, friction injection rate, fraud chargeback or downstream-loss correlation
  • 03Tier responses: low-risk → allow, medium → step-up, high → quarantine, certain → deny + investigate
  • 04Replay flows from suspect ASNs / device fingerprints in shadow mode before enforcing — false-positive cost is high

API9 — discovery is the prerequisite for everything else

Improper Inventory Management is the entry CISOs underestimate the most. Across our 2024–2025 API security assessments, the gap between client-believed API count and discovered API count averaged 38%. The undocumented APIs carry disproportionate BOLA and BOPLA debt because no one tested them.

A real discovery program triangulates from at least three sources: traffic-layer (gateway / mesh / WAF logs), code-layer (route definitions in source repos), and observability-layer (APM / OpenTelemetry traces). The intersection is the inventory; the differences are the work.

/API_DISCOVERY_SOURCES

SourceCatchesMisses
Gateway / WAF logsAnything reaching the front doorInternal-only / east-west APIs
Source-code route scanDefined routes per serviceDynamically registered routes; orphan deployments
APM / OTel tracesAnything that runs in productionCold endpoints, never-called legacy
Service mesh telemetryEast-west flowsAnything outside the mesh

The four KPIs that prove your API security program works

/API_BOARD_KPIS

KPITargetWhat it proves
BOLA contract-test coverage≥ 95% of routes with object IDsAPI1 is regression-tested in CI
BOPLA property allow-listing100% of authenticated routesAPI3 is enforced at the API layer
Inventory drift< 5% gap between code, traffic, meshAPI9 is under control
Friction-injection rate on sensitive flowsTrending with abuse-attempt rateAPI6 detection is real

A 90-day uplift plan

  1. 01Days 0–30 — Stand up triangulated API discovery (gateway + code + traces). Publish the inventory delta. Assign owners to every discovered shadow / zombie API.
  2. 02Days 30–60 — Land BOLA + BOPLA contract tests in CI for the top 20 highest-risk routes. Gate merges on them. Expand coverage weekly.
  3. 03Days 60–90 — Inventory the sensitive business flows (signup, refund, coupon, balance lookup). Stand up behavioral instrumentation in shadow mode. Publish the four board KPIs.
/MONDAY_PLAYBOOK

Monday morning — the test that surfaces 60% of BOLAs in an afternoon.

Pick three of your highest-traffic authenticated APIs. Take a known-good request. Replace the object ID in the URL or body with an ID owned by another tenant. If you get a 200 back, you have a P1 and the same bug almost certainly exists elsewhere. Build the contract test before lunch and run it across the route table by end of day.

  • ▸Pick three highest-traffic authenticated routes
  • ▸Replay with a foreign-tenant object ID
  • ▸If any returns 200, ticket as P1 and pattern-match across the route table
  • ▸Convert the manual test to a CI assertion before EOD

Closing — authorization is the whole game

Cryptographic mistakes are rare in modern APIs. Injection is largely solved by parameterized queries and ORMs. Authentication, while still a source of bugs, has good defaults in every major framework. Authorization remains custom code in every API and that is exactly why it remains the dominant failure mode. Invest your appsec dollars where the bugs actually live: object-level, property-level, function-level, and flow-level authorization. The 2023 OWASP API Top 10 finally tells you so without flinching.

#OWASP#API Security#BOLA#BOPLA#AppSec

/WRITTEN_BY

Marco Pereira

Principal Application Security Engineer · Alexa Cybersecurity