- Broken Object Level Authorization (BOLA) โ the most common API vulnerability
- Broken Authentication
- Broken Object Property Level Authorization (excessive data exposure & mass assignment)
- Unrestricted Resource Consumption and Lack of Rate Limiting
- Security Misconfiguration and Improper Inventory Management
- A real-world example
- Common mistakes to avoid
- Frequently asked questions
OWASP API Security Top 10 Explained
Every API you ship is a documented invitation. Publish an OpenAPI spec, and you've handed attackers a map of every endpoint, parameter, and object type your backend exposes โ no need to reverse-engineer a UI or guess at hidden form fields. That convenience for developers is exactly what makes APIs a distinct and increasingly favored attack surface, and it's why the OWASP API Security Top 10 exists as a separate list from the general OWASP Top 10.
Traditional web app security assumes a browser sits between the user and the server, rendering forms and hiding logic behind client-side flows. APIs strip that away. There's no UI to obscure a parameter, no client-side validation an attacker has to route around โ just a URL, a method, and a payload, all callable directly with curl. That shift changes which vulnerabilities matter most: injection and cross-site scripting still exist, but the risks that dominate real-world API breaches are authorization failures, data exposure at the object and property level, and infrastructure that nobody remembered was still running. This article walks through the categories that matter most in practice, in the order they tend to bite production systems.
Broken Object Level Authorization (BOLA) โ the most common API vulnerability
BOLA sits at the top of the OWASP API Security Top 10 for a reason: it's the single most frequently exploited API flaw in the wild, and it's dangerously easy to introduce without noticing. The bug pattern is simple. An endpoint like GET /api/orders/12345 checks that the request carries a valid session or token โ that is, it confirms authentication โ but never checks whether the authenticated user actually owns order 12345. That second check, authorization at the level of the specific object being requested, is the part that goes missing.
The result is an Insecure Direct Object Reference (IDOR)-style flaw wearing an API costume. Swap the ID in the URL, and if the backend's only gate is "is this token valid," you're now looking at someone else's order, invoice, medical record, or direct message. This is especially dangerous with sequential or predictable identifiers, but it's just as exploitable with UUIDs if an attacker can harvest them from another response (a list endpoint, a webhook payload, a leaked support ticket).
The fix has to happen on every single object-returning endpoint, not just the obvious ones: after you've established who the caller is, explicitly verify that the requested resource belongs to them, or that their role grants access to it, before you touch the database record or return it. Ownership checks belong in the data access layer, ideally enforced consistently rather than re-implemented ad hoc per route, because a single missed endpoint reintroduces the whole class of bug.
Being logged in tells the server who you are. It says nothing about whether you're allowed to open this particular door.
Broken Authentication
Authentication flaws in APIs tend to cluster around three failure modes. First, missing or weak rate limiting on authentication endpoints โ /api/login, /api/password-reset, /api/token/refresh โ leaves the door open to credential stuffing, where attackers replay breached username/password pairs from other services at scale, betting on password reuse. Without per-account and per-IP throttling, an API can process thousands of login attempts a minute with no friction at all.
Second, weak JWT validation is a recurring and severe mistake. Some JWT libraries historically accepted the "alg": "none" header, meaning a token with an empty signature would be treated as valid if the server didn't explicitly reject it. Others fail to verify the signature at all, or trust the algorithm specified in the token header rather than pinning it server-side โ which opens the door to algorithm-confusion attacks where an RS256-signed token is swapped for one forged with the public key used as an HMAC secret. Every JWT-based API needs to hardcode the expected algorithm, verify the signature on every request, and validate standard claims like exp and aud rather than trusting the payload's face value.
Third, credential exposure through overly permissive CORS, tokens with no expiry, or refresh tokens that never get revoked all extend the blast radius once an attacker has a foothold. Short-lived access tokens paired with revocable refresh tokens limit how long a single leaked credential stays useful.
Broken Object Property Level Authorization (excessive data exposure & mass assignment)
This category covers two related but distinct mistakes, both stemming from binding API responses and requests directly to internal data models instead of explicit, filtered schemas.
Excessive data exposure happens on the response side: an endpoint returns the entire internal user object โ including fields like passwordHash, internalNotes, or ssn โ and relies on the client application to only display the fields it needs. That's a dangerous assumption, because anyone calling the API directly sees everything, filtered or not. The fix is to define explicit response schemas per endpoint and serialize only the fields that are meant to be public, rather than trusting the frontend to hide what the backend already sent.
Mass assignment is the mirror image on the request side. If an endpoint takes the client's JSON body and binds it directly onto an internal model โ a common convenience in many frameworks โ an attacker can add fields the UI never exposes. A profile update endpoint that expects {"name": "...", "email": "..."} might, if the backend blindly deserializes the whole payload, also accept {"isAdmin": true} or {"accountBalance": 999999} if those fields exist on the underlying model and nothing explicitly blocks them. The defense is an allowlist: only bind the specific fields a given operation is supposed to accept, never the full object graph.
Unrestricted Resource Consumption and Lack of Rate Limiting
APIs that impose no limits on payload size, response size, query complexity, or request frequency are an availability risk even without a motivated attacker. A GraphQL endpoint with no query depth or complexity limits lets a single request fan out into thousands of nested database calls. A REST endpoint accepting unbounded limit or page_size parameters can be asked to return millions of rows in one call. File upload endpoints with no size cap can be used to exhaust disk or memory.
This isn't purely a denial-of-service concern, either โ it's a cost-control concern. Auto-scaling infrastructure billed by compute and bandwidth turns unrestricted resource consumption into a direct line to a very large cloud bill, sometimes from legitimate but poorly-behaved client code rather than malice. Effective controls include rate limiting per API key or user (not just per IP, which is easy to distribute around), maximum payload sizes, pagination caps, query complexity analysis for GraphQL, and timeouts on any endpoint that triggers expensive downstream work.
Security Misconfiguration and Improper Inventory Management
This is where API sprawl becomes a security problem in its own right. Three patterns show up repeatedly in breach postmortems. Deprecated API versions often stay reachable long after the "current" version replaces them โ /api/v1/users might have none of the authorization fixes applied to /api/v2/users, but if it's never decommissioned, it's still a live path into the same backend. Verbose error handling is the second pattern: stack traces, database error messages, or internal file paths returned in a 500 response hand attackers a debugging session for free, revealing framework versions, table names, and query structure.
The third and increasingly common pattern is shadow APIs โ endpoints that exist in production but were never documented, added to an inventory, or included in a security review. These accumulate from abandoned features, internal debugging routes left in by developers, staging endpoints promoted to production, and third-party integrations nobody tracked centrally. An endpoint nobody knows about is an endpoint nobody is monitoring, patching, or rate-limiting, which makes API discovery and inventory management a prerequisite for every other control on this list โ you cannot secure what you don't know exists.
A real-world example
A common pattern reported across bug bounty programs looks like this: a security researcher testing an e-commerce API notices that after placing an order, the confirmation page calls GET /api/orders/48213 to display the receipt. The researcher, authenticated as a legitimate low-privilege customer, decrements the ID to 48212 and requests it again. The response returns a complete stranger's order โ their shipping address, the last four digits of their payment card, and their full name and phone number.
The root cause is textbook BOLA: the endpoint's authorization logic checked only that the request carried a valid session token, never whether the session's user ID matched the userId field on the order record being fetched. Because order IDs were sequential integers, the researcher could enumerate the entire order history of every customer on the platform simply by iterating the ID, no automation required beyond a basic loop. The fix, once identified, was a single added clause to the query โ filtering by the authenticated user's ID alongside the order ID โ but the exposure window before discovery had already let the flaw sit in production, unmonitored, for months. This is precisely why BOLA leads the OWASP API Security Top 10: the vulnerability is trivial to introduce, trivial to exploit, and produces a direct, high-value data leak with no need to bypass encryption, exploit memory corruption, or chain multiple bugs together.
Common mistakes to avoid
Treating a valid token as sufficient authorization. Authentication answers "who are you"; it says nothing about "should you see this specific record." Every object-returning or object-modifying endpoint needs its own explicit ownership or permission check โ assuming the auth middleware already handled it is how BOLA gets shipped.
Trusting client-supplied fields for anything security-sensitive. Role flags, price fields, ownership IDs, and permission levels should never be taken from the request body at face value. If the client can set it, assume an attacker will try setting it to something you didn't intend, and re-derive or re-validate anything that affects authorization or business logic server-side.
Having no real inventory of what's actually live. Teams routinely underestimate how many API versions, environments, and forgotten endpoints are reachable from the public internet. Without a maintained inventory โ ideally generated from actual traffic and gateway logs, not just what's in the current OpenAPI spec โ old and shadow endpoints stay exposed indefinitely, invisible to every other security control you've invested in.
Frequently asked questions
Is the OWASP API Security Top 10 the same as the regular OWASP Top 10?
No. They're separate projects covering different risk profiles. The general OWASP Top 10 focuses on web application vulnerabilities like injection and cross-site scripting. The API Security Top 10 is built specifically around how APIs are attacked โ object- and property-level authorization failures, resource consumption abuse, and inventory blind spots โ because APIs lack the UI layer that shapes traditional web app threats.
Why is BOLA ranked as the top API risk instead of injection?
Injection flaws are still dangerous, but BOLA requires no special tooling, no payload crafting, and no bypassing of input validation โ just a valid account and a predictable or guessable identifier. That low barrier to exploitation, combined with how frequently it's found in real APIs, is why it consistently tops incident reports and bug bounty payouts.
Can API gateways or WAFs fully solve these problems?
They help with some categories โ rate limiting, schema validation, and blocking known-bad patterns are gateway-level wins โ but object-level and property-level authorization logic depends on business context the gateway doesn't have. Only application code that knows "this order belongs to this user" can enforce that check correctly, so gateways are a layer of defense, not a substitute for authorization logic in the API itself.
The throughline across all of these categories is that APIs fail quietly. A broken object-level check doesn't throw an error or crash a page โ it just returns data it shouldn't, to someone who technically had a valid token. Closing that gap means treating authorization as a per-object, per-field decision made on every request, keeping a real inventory of what's actually running, and never trusting the client to enforce anything security-relevant on your behalf.
Keep Learning on ITVedas
One of many free guides across 8 IT chapters โ all in plain English.
Explore All Chapters โ