What is IDOR (insecure direct object reference)?

IDOR, an insecure direct object reference, is an access-control vulnerability: an application uses an identifier from the request, such as /api/orders/1042, to fetch a record without checking that the caller may see it. Changing the number then returns somebody else's order, invoice or profile.

Why it matters

IDOR needs no special tooling and no clever payload, only a second account and the patience to change one value. That simplicity is why it is one of the first things a tester tries on any app with accounts, and why it is so easy to ship: the code that loads the record works correctly, and the one line that should compare the record's owner with the logged-in user is simply missing.

MITRE files it as CWE-639, authorization bypass through user-controlled key, and the OWASP Top 10:2025 lists that weakness under A01, broken access control, the first category of the list. In APIs the same bug is called BOLA, and the OWASP API Security Top 10 2023 ranks it first.

Example: testing for IDOR on CyberGym or your own app

CyberGym, the legal practice target, keeps a shopping basket per user at /rest/basket/<id>. Without a session the endpoint refuses, which shows it checks authentication:

$ curl -s -o /dev/null -w "%{http_code}\n" https://cybergym.hackergpt.app/rest/basket/1
401

Authentication is not the question IDOR asks. The test is: log in as user A, note the ID of A's basket, then ask for a neighbouring ID with A's session. If the response holds another user's basket, the endpoint checks that you are logged in but not that the basket is yours. CyberGym is built to contain bugs of this kind, so you can watch it happen on a target that permits it.

On your own app, do the same with two test accounts you create, one request per endpoint that takes an ID. Look at numeric IDs first, then at IDs in JSON bodies, headers and file names. The fix is a server-side ownership check on every lookup, not a harder-to-guess ID.

Common mistakes

  • Relying on random IDs. A UUID is harder to guess but leaks in URLs, logs and shared links. It slows discovery; it does not authorize the request.
  • Testing with only one account. IDOR is about crossing between users, so you need at least two, ideally with different roles.
  • Checking reads but not writes. PUT, PATCH and DELETE on someone else's record are the same bug with worse consequences.
  • Fixing it in the front end. Hiding other users' IDs in the interface changes nothing for a direct request.

Related terms

Go deeper

Sources

Test only sites you own or have written permission to test. To practise without one, use CyberGym, a legal, deliberately vulnerable target. Practise on CyberGym.