IDOR and Access Control in AI APIs, by the Numbers
OWASP ranks broken access control the top web risk and BOLA the top API risk. Real prevalence and attack data, and what BrassCoders can honestly flag.
OWASP’s Top 10 2021 found broken access control in 94% of tested applications — the highest occurrence count of any category, at 318,487 logged instances. The API-specific version of the same bug, Broken Object Level Authorization, ranks first in OWASP’s API Security Top 10 2023 and showed up in 27% of real attack traffic against production APIs in Salt Labs’ most recent report. An AI assistant asked for a REST endpoint that returns a user’s record will write one without hesitation. Whether it checks that the caller owns that record is a separate question, and the data below says it usually never gets asked. This post walks through the prevalence and attack numbers, then draws the line most AI-code-security writing skips: which of these patterns a deterministic scanner can flag, and which require a human, or an AI assistant with real context, to judge.
Broken Access Control Is OWASP’s Most Common Finding
BrassCoders treats OWASP’s Top 10 2021 ranking as the baseline number for how often this class of bug survives into a tested application. Broken Access Control moved from fifth place in the 2017 list to first in 2021, present in 94% of applications OWASP’s contributors tested, with 318,487 total occurrences mapped across 34 separate CWEs — more raw occurrences than any other 2021 category.
The average incidence rate across those 34 CWEs sits at 3.81%, but the ceiling runs far higher: the single most common CWE inside the category peaks at a 55.97% incidence rate among the applications where it was tested. OWASP’s A01:2021 Broken Access Control page also logs 19,013 CVEs tied to the category, a volume that puts it ahead of injection, cryptographic failures, and every other 2021 category by raw occurrence count. Access control is a category, not one bug, and IDOR is one of the shapes it takes most often.
The 34 CWEs mapped into A01:2021 span path traversal, forced browsing past access checks, and privilege escalation alongside the identifier-swap pattern IDOR describes. That range is part of why access control rarely shows up as a single named line item on a vulnerability report — it’s a family of related gaps, and an IDOR is the member of that family an API endpoint runs into first.
BOLA Is the API-Specific Name for the Same Failure
BrassCoders treats OWASP’s API Security Top 10 2023 as the sharper, API-specific lens on the same category. API1:2023 Broken Object Level Authorization ranks first among API risks, and OWASP rates the underlying weakness widespread in prevalence and easy for both an attacker to exploit and a tester to detect, once someone knows to look.
OWASP’s API1:2023 entry describes the mechanics plainly: an API exposes an object identifier somewhere in the request, sequential integer, UUID, or plain string, and the server trusts that identifier without checking whether the caller may touch the object behind it. IDOR is the general term for this failure in any application, web page or API alike. BOLA is what it looks like on an API endpoint. The identifier moves from a URL path on a web form to a JSON field or query parameter, and the fix stays identical either way: compare the caller’s identity against the resource’s owner before the response goes out.
The Attacks Are Already Happening in Production Traffic
BrassCoders treats Salt Labs’ Q1 2025 State of API Security Report as evidence that BOLA isn’t a finding that only shows up in a pentest write-up. Drawn from 206 surveyed IT and security professionals plus anonymized traffic from Salt Security’s own customers, the report found broken object-level authorization responsible for 27% of observed attack traffic, with BOLA and injection attacks combined behind 37% of the production API issues respondents reported.
Two more numbers from the same report frame the stakes. Ninety-nine percent of respondents said they’d hit some kind of API security issue in the past 12 months, and 55% had slowed the rollout of a new application specifically over API security concerns. Salt Labs’ report frames this as an attack surface growing faster than most teams’ review capacity can keep up with. An AI assistant generating new endpoints every sprint adds straight to that surface. Each one is a fresh object-level check that either exists or doesn’t.
Why AI-Generated APIs Skip the Ownership Check by Default
BrassCoders sees the same shape repeatedly across AI-generated CRUD endpoints: a handler that accepts an object ID, fetches the row, and returns it, with no comparison against the caller’s identity anywhere in the function. The pattern is not a training defect. It’s the natural result of a prompt that specifies what an endpoint returns without specifying who’s allowed to ask for it.
Ask an AI assistant for get user by id and it produces exactly that: a route, a database lookup, a response. Ownership is a fact that lives in your application’s data model, not in the prompt, and an assistant that hasn’t been told which callers should reach which records has no way to add the check unprompted. The result reads as complete code. It passes type-checking and a casual review, because every line does what it appears to do. The missing line, the one comparing the caller’s ID against the resource owner, leaves no syntactic gap for a scanner or a reviewer to notice — which is exactly why OWASP rates the underlying weakness easy to exploit and hard to catch by accident.
The gap compounds when the same assistant generates several similar endpoints in one sitting: get by id, update by id, delete by id, list by owner, each one a fresh instance of the same missing comparison. A developer writing that dozen routes by hand might carry the ownership rule forward mentally after the first one. An assistant regenerating each handler from a fresh prompt has no such continuity unless the project’s authorization pattern is written down somewhere it can read.
What a Benchmark Like crAPI Actually Tests
BrassCoders treats OWASP’s crAPI project as the concrete way to test whether a detection layer or a review process actually catches BOLA, instead of trusting that it would. Short for completely ridiculous API, crAPI is a deliberately vulnerable car-marketplace application, built as a multi-service stack and modeled directly on the OWASP API Security Top 10, with BOLA scenarios included by design.
The project carries more than 1,600 stars on GitHub and ships a documented set of challenges rather than one bug to find. Running a scanner, an AI code-review session, or a manual test plan against crAPI answers a narrower and more useful question than whether it catches IDOR in general: whether it catches this specific object-level authorization gap, in this specific vulnerable app, where the answer is already known. Builders who want a sanity check on their own detection stack have somewhere to point it before trusting that stack against a real API.
What BrassCoders Can and Cannot Flag
BrassCoders does not detect IDOR or BOLA directly, because confirming an ownership check is correct requires knowing the application’s authorization rules, and that context lives outside any single file a scanner reads. What BrassCoders’ 12 bundled scanners do flag: routes with no visible auth decorator where the framework makes one detectable, mass-assignment-shaped update calls that write every request field to a database row, and hardcoded credentials sitting in the same handler.
Semgrep, one of the scanners inside BrassCoders’ OSS core, is the pattern-matching engine behind that structural layer. It can match the shape of a missing decorator or a suspicious field-mapping loop, but it cannot evaluate whether the comparison inside an existing check uses the right field. That evaluation is a judgment about your data model, and BrassCoders hands it to the AI assistant reading its YAML output, or to a human reviewer, rather than guessing at it. Reporting the structural pattern honestly, without pretending to have verified the logic behind it, is the design choice. A wrong demotion here would be worse than an unflagged gap, because it would tell the AI triage layer the finding was already checked when it wasn’t.
The same honesty applies in the other direction. A scanner that guessed right most of the time and stayed silent the rest would train an AI triage layer to trust that silence, and the one case where the guess failed is the one that ships. BrassCoders’ scanners report what they can verify structurally and nothing more. That’s a narrower claim than detecting IDOR outright, but a more honest one — and it’s the claim an AI assistant reading the YAML output can actually build on.
What Actually Catches an IDOR Before It Ships
BrassCoders points builders at the same fix OWASP’s own testing guidance recommends: write a test that requests every object-returning or object-modifying endpoint as a user who shouldn’t have access, and assert a rejection instead of a 200. That test doesn’t require a scanner at all. It requires enumerating who owns what, which is exactly the step an AI assistant skips when nobody tells it the answer.
Threat modeling before the code exists, authorization tests that run in CI, and DAST or manual testing against the live app are the three controls OWASP names as the ones that actually reason about intent instead of code shape. None of them are exotic. All three require someone to write down who should reach which resource — a step that’s easy to skip under a deadline and impossible for a pattern scanner to reconstruct after the fact.
Practically, that means an authorization test suite grows in step with the endpoint list rather than as an afterthought scheduled for later. Every new object-returning route gets a companion test asserting what happens when someone who doesn’t own the object asks for it anyway. That test is cheap to write once the ownership rule is known, and it catches the exact class of bug the numbers above describe before it reaches a review, a scanner, or an attacker.
BrassCoders runs on macOS, Linux, and Windows (WSL2). Install with:
pip install brasscoders
brasscoders scan /path/to/your/api
The OSS core is Apache 2.0 and free. BrassCoders Paid adds AI-powered enrichment for $12/dev/month — 50M tokens included, cancel any time via brasscoders portal.
Frequently Asked Questions
What is IDOR, and how is it different from BOLA?
IDOR, Insecure Direct Object Reference, and BOLA, Broken Object Level Authorization, name the same bug: an endpoint accepts an object ID from the caller and returns or changes that object without confirming ownership. IDOR is the older, general term. BOLA is OWASP's API-specific name for it, ranked API1 in the OWASP API Security Top 10 2023.
How common is broken access control across web applications?
OWASP's Top 10 2021 found broken access control present in 94% of tested applications, with 318,487 occurrences logged across 34 mapped CWEs — more occurrences than any other category in the dataset, and the reason it jumped from fifth place in 2017 to first in 2021.
How often does BOLA show up in real attacks against production APIs?
Salt Labs' Q1 2025 State of API Security Report found broken object-level authorization behind 27% of observed attack traffic against its customers' APIs, with BOLA and injection attacks combined responsible for 37% of production API issues respondents reported.
Can a static analysis scanner detect an IDOR or BOLA bug directly?
Not reliably. Whether an ownership check is correct depends on the application's data model, a fact about intent with no consistent code shape to match. BrassCoders flags structural neighbors instead — missing auth decorators, mass-assignment-shaped update calls — and leaves the ownership-logic judgment to the AI triage layer or a human reviewer.
What does BrassCoders actually flag around access control?
BrassCoders' bundled scanners, Semgrep among them, pattern-match structural signals next to access-control bugs: routes with no visible auth decorator, update calls that write every request field to a database row, and hardcoded credentials in route handlers. It does not verify that an authorization check enforces the correct ownership model.
How do I test whether my API actually blocks IDOR before shipping?
Write authorization tests that request each object as a user who should not have access, and assert a 403 or 404 instead of a 200 with someone else's data. OWASP's crAPI project provides a deliberately vulnerable API, BOLA included, for practicing exactly that test before running it against a real system.