04 Attackers and architecture · Advanced

What Is IDOR (Insecure Direct Object Reference)?

5 of 12 in Attackers and architecture · 4 min read · Updated

Read first: Authentication and authorization, What Is the OWASP Top 10?

Definition

An IDOR (Insecure Direct Object Reference) is an access control vulnerability where an application uses an identifier supplied by the user, such as /invoices/1042, to fetch an object without checking that the user is allowed to access it. Changing the ID returns someone else's data. In API security the same flaw is called BOLA (Broken Object Level Authorization).

IDOR is one of the simplest vulnerabilities to exploit and one of the most damaging. There's no exploit code and no special tool: an attacker logs in to their own account, notices an ID in a URL or API request, changes it, and gets someone else's data. It's consistently among the most reported issues in bug bounty programmes and the root cause of many large data exposures.

How IDOR works

An application exposes a direct reference to an internal object, usually a database ID, and trusts it:

GET /api/invoices/1042
Authorization: Bearer <token for customer A>

// server
invoice = db.invoices.find(params.id)   // no ownership check
return invoice

The request is authenticated: the server knows it's customer A. It isn't authorized: nothing checks that invoice 1042 belongs to customer A. Changing the ID to 1043 returns customer B's invoice.

The same pattern appears anywhere an identifier comes from the client:

  • Reading: GET /users/57/profile, /download?file=report-2291.pdf
  • Changing: PUT /orders/889 with a modified body
  • Deleting: DELETE /projects/31
  • Hidden fields: an account_id in a JSON body or form, separate from the URL
  • Function-level: calling POST /admin/users/57/reset as a normal user (strictly, broken function-level authorization, IDOR's close relative)

IDOR, BOLA and where they're classified

IDOR was its own category in the OWASP Top 10 from 2007 to 2013, then merged into Broken Access Control, which has ranked first since 2021 and kept the top spot in the 2025 edition. For APIs, the OWASP API Security Top 10 calls it BOLA (Broken Object Level Authorization) and ranks it first. The weakness is CWE-639, Authorization Bypass Through User-Controlled Key.

Why it's so common

  • Authorization is per endpoint. Authentication is handled once by middleware; ownership has to be checked in every handler, and one forgotten check is enough.
  • The UI hides it. The frontend only ever shows a user their own invoices, so manual testing never tries anyone else's.
  • APIs multiply. Mobile apps, partner APIs, exports and old API versions each need the same check.
  • Object graphs. The invoice endpoint checks ownership, but /invoices/1042/attachments/7 only checks that attachment 7 exists.

Worked example: Invoicely

IDOR was the highest-scoring threat in the Invoicely threat model:

T2: A customer can read another customer's invoices by changing the invoice ID in the API, because ownership is checked in the UI but not on every endpoint. Likelihood 4 × impact 5 = 20, critical.

The attack tree shows why it outscored everything else: the IDOR branch needs only a free account and a browser's developer tools, while the other paths to the same goal need phishing, stolen credentials or an insider. The fix: every query in the data access layer is scoped to the authenticated customer (where account_id = session.account_id), plus automated tests that log in as one customer and request another's invoices, PDFs and attachments.

How to prevent IDOR

  1. Check authorization on every object access. Not just "is the user logged in", but "may this user perform this action on this object".
  2. Enforce it in one place. Scope queries by the caller's tenant or user in the repository or ORM layer (for example, query scopes or row-level security in the database), so a new endpoint inherits the check instead of re-implementing it.
  3. Take identity from the session, not the request. Ignore user_id or account_id in request bodies; derive them from the authenticated token.
  4. Deny by default. Return 404 rather than 403 for objects the caller can't see, so attackers can't confirm an ID exists.
  5. Use unguessable IDs as defence in depth. UUIDs reduce enumeration but are not an access control.
  6. Test across accounts. Add automated tests with two users that try to read, change and delete each other's objects through every endpoint.

Finding IDOR in a threat model

On the data flow diagram, draw a trust boundary around each tenant's or user's data, even if it lives in a shared database. Every flow from the API into that store crosses a boundary between "any authenticated user" and "this user's data", and for each one, ask: where is ownership enforced? For multi-tenant systems, our guide to threat modeling multi-tenant SaaS covers tenant isolation in depth.

Common mistakes

  • Fixing the reported endpoint only. An IDOR report is usually evidence of a missing pattern. Search for every endpoint with the same shape.
  • Relying on obscure IDs. IDs leak through shared links, logs, referrer headers and other API responses.
  • Forgetting nested and bulk endpoints. Exports, search, GraphQL resolvers and batch operations need the same check.

Key takeaways

  • IDOR happens when the server fetches an object by an ID from the request and never checks the caller is allowed to have it.
  • It needs no special skill: a logged-in account and the ability to edit a URL or request body are enough.
  • Random IDs (UUIDs) make IDOR harder to find, not impossible. The fix is an authorization check on every object access.
  • Enforce ownership in one shared place, such as the data access layer, and test it by logging in as user A and requesting user B's objects.

Frequently asked questions

What is an IDOR example?

A user views their invoice at /api/invoices/1042, changes the number to 1043 and receives another customer's invoice, because the API checks they are logged in but not that invoice 1043 belongs to them.

What is the difference between IDOR and BOLA?

They describe the same flaw. IDOR is the older term, from the OWASP Top 10 of 2007 to 2013. BOLA, Broken Object Level Authorization, is the term used by the OWASP API Security Top 10, where it has been ranked first in both the 2019 and 2023 editions.

Do UUIDs prevent IDOR?

No. Unguessable IDs make enumeration harder, but IDs leak through URLs, logs, shared links, browser history and other API responses. Once an attacker has one, there is still no authorization check to stop them.

Which OWASP Top 10 category covers IDOR?

A01 Broken Access Control, which has been the top category since the 2021 edition and kept that position in the 2025 edition. The matching weakness is CWE-639, Authorization Bypass Through User-Controlled Key.

Find IDORs at the design stage

In a ThreatTree DFD, a trust boundary around each tenant's data makes every flow that crosses it explicit. An attack tree for "read another customer's data" then lists each endpoint as a leaf, scored on likelihood and impact, so the missing check is found before the pen test.

Every plan, Free included, comes with four finished example threat models you can open and change.

Get started free

Get new knowledge-base entries and threat-modeling guides by email.