← back to index
METHODOLOGY 20 JAN 2026 · 9 min read

IDOR in the Wild

Why insecure direct object references still pay bounties — and where to look in 2026.

An IDOR is not a clever bug. It is the absence of one specific check, in one specific handler, on one specific endpoint. Companies ship them constantly because authorization is harder than authentication, and it scales worse.

What IDOR actually is

The textbook definition — "an attacker changes an ID in a URL and accesses someone else's data" — is correct but small. The real definition: the application accepts an identifier from the client and returns or modifies the corresponding resource without checking that the current user is allowed to interact with it.

The identifier might be in:

  • A URL path: /api/invoices/4821
  • A query string: ?file_id=4821
  • A request body: {"target_user": 4821}
  • A header: X-Account-Id: 4821
  • A cookie, occasionally — and those are gold when you find them.
  • A websocket frame.
  • A GraphQL query argument.

"UUIDs make this safe" is a myth. UUIDs only make the bug harder to find by enumeration. They do nothing about the underlying authorization gap. If you can leak, share, or reference a UUID anywhere — invitations, public profiles, support tickets, share links — the bug is still there.

The methodology that keeps paying

Every productive IDOR session I've ever had follows roughly the same loop:

  1. Map the resource model. What objects does the app have? Users, projects, files, messages, invoices, comments, drafts, exports. For each, find the create / read / update / delete endpoints.
  2. Use two accounts. Always. Account A creates resources. Account B, in a different browser profile, tries to access them by ID.
  3. Test every HTTP verb. GET might be locked down. PUT, PATCH, and DELETE on the same path frequently are not — different developers, different decade, different review.
  4. Test every related action. If you can't read an object, can you share it? Export it? Add a collaborator to it? Comment on it? Each side action is a separate authorization decision.
  5. Look for "force browse" via UI traversal. The app navigates from project → file. Skip the project step. Hit the file endpoint directly with an ID you guessed.

Higher-order IDOR patterns

Once you've cleared the obvious cases, the bigger bounties live in second-order issues:

Mass assignment

PATCH /api/users/me
{ "email": "new@x.com", "role": "admin", "tenant_id": 99 }

The endpoint expects you to update your email. The serializer accepts whatever you throw at it. Suddenly you've changed your role, or moved your account into someone else's tenant. This is IDOR-adjacent and deeply rewarding.

Stale references

You were a member of a project, then removed. Does your old API token still work against that project's endpoints? Often yes. Token-bound vs. membership-bound permission checks are commonly inconsistent.

Indirect references

Some apps replaced numeric IDs with "secure" tokens — but the token is just base64(user_id + ":" + invoice_id). Decode every opaque identifier you encounter. The number of times this works is embarrassing to the industry.

GraphQL nesting

GraphQL frequently has authorization on root queries but not on nested fields. viewer { otherUsers(id: 4821) { email } }-style queries are an entire sub-genre. Test every relation; do not assume the field-level resolver checks anything.

Bulk endpoints

Per-item auth is implemented; bulk-action endpoints frequently are not. POST /api/files/bulk-delete with a body containing files you don't own is a classic.

Why companies still ship them

Authorization is contextual in a way authentication is not. "Is this person logged in?" has one answer. "Is this person allowed to do this to that?" depends on the resource type, the relationship between user and resource, the current state of both, and any number of business rules.

That contextual nature means authorization checks have to be re-implemented for every new feature, by whichever engineer happens to be writing it. Frameworks help — policy systems, ABAC libraries, row-level-security in the database — but only if used consistently. They almost never are.

That gap is your job security as a hunter. Be patient, be systematic, and keep two accounts logged in side by side. The bugs are still there.