On this page
  1. What is IDOR?
  2. How it works
  3. Why it’s so common
  4. Where AI coding assistants get this wrong
  5. Checklist
  6. FAQ
    1. Is IDOR the same as broken access control?
    2. Does using UUIDs prevent IDOR?
    3. How do I test for IDOR?
  7. Related topics
  8. Sources
concept

What Is Broken Access Control (IDOR)?

IDOR lets users access other people's data by changing an ID in a request when the app never checks ownership. Learn how it works and how to fix it.

Quick answer

  • IDOR (insecure direct object reference) lets a user access objects they don’t own by changing an identifier in a request.
  • The root cause is missing authorization checks: the app fetches the object without verifying the caller owns it.
  • It’s part of broken access control, the top category in the OWASP Top 10.

What is IDOR?

IDOR is a vulnerability where an application exposes a direct reference to an internal object — an ID, a filename, a key — and fails to check that the requesting user is allowed to access it. If a user can change GET /invoices/1234 to GET /invoices/1235 and see someone else’s invoice, that’s an IDOR. The bug isn’t the reference itself; it’s the missing authorization check on the lookup.

How it works

A typical vulnerable endpoint reads the ID from the URL and queries the database directly:

@app.get("/invoices/{invoice_id}")
def get_invoice(invoice_id: int):
    return db.query(Invoice).get(invoice_id)  # no ownership check

Because the code never verifies that the current user owns invoice_id, any authenticated user can enumerate every invoice. The flaw is invisible in normal use — it only appears when someone changes a number.

Why it’s so common

Access control is per-application logic that no framework can add automatically, and it’s exactly the kind of subtle, context-specific check that AI assistants omit. This is why broken access control, not exotic exploits, tops the OWASP list, and why IDOR is the canonical example found in AI-generated CRUD apps.

Where this bites vibecoders

The fastest way to ship a CRUD app with an AI assistant is exactly how IDOR ships: generate list/get/update endpoints, wire them to the database, and never add ownership checks. Every get(id) is a potential leak until you explicitly ask “is this object the current user’s?” — and that’s the one question the generated code never asks on its own.

Where AI coding assistants get this wrong

  • Generating CRUD endpoints with direct object lookups and no authorization.
  • Checking only that a user is logged in, not that they own the specific object.
  • Treating “the ID is a UUID/unguessable” as a substitute for authorization.
  • Adding the check inconsistently — some endpoints guarded, others not.

Checklist

  • Add an ownership/authorization check on every object access, not just login.
  • Fetch objects through the current user’s scope (e.g., user.invoices.get(id)).
  • Test by changing IDs across accounts and confirming access is denied.
  • Treat unguessable IDs as defense in depth, never the whole control.
  • Cover every endpoint, including admin and bulk operations.

FAQ

Is IDOR the same as broken access control?

IDOR is one specific form of broken access control — the case where a direct object reference is exposed without an ownership check. Broken access control is the broader category that also covers missing role checks and privilege escalation.

Does using UUIDs prevent IDOR?

No. A UUID makes IDs hard to guess but doesn’t stop an authorized user from accessing objects they shouldn’t if the app returns other users’ data when given their UUID. Obscurity is not authorization.

How do I test for IDOR?

Create two accounts, note an object’s ID under one, and request it while authenticated as the other. If the second account can read or modify it, the check is missing. See How to Test Your App for Broken Access Control.

Sources

Share: