Journal / Security, Auth, and Compliance

Security, Auth, and Compliance

Insecure Direct Object References: The Bug Founders Underestimate

An Insecure Direct Object Reference (IDOR) is a vulnerability where an application exposes internal object identifiers in URLs or API requests without verifying that the requesting user has permission to access the referenced object. The result is that any user can access any other user's data by guessing or enumerating the identifier. IDOR vulnerabilities are consistently in the OWASP Top 10 and are among the most commonly reported in bug bounty programs.

What you need to know

  • IDOR vulnerabilities result from missing authorization checks, not from using sequential IDs. UUIDs reduce guessability but do not prevent the bug.
  • Every API endpoint that accepts an object identifier must verify that the authenticated user has permission to access the referenced object. Authentication proves who you are. Authorization proves what you can access.
  • IDOR is consistently one of the highest severity findings in bug bounty programs and security audits because it often grants direct access to other customers' data.
  • Row level security at the database level provides a defense in depth layer against IDOR. Postgres RLS and equivalent features in other databases enforce authorization at the data layer, not just the API layer.
  • Testing for IDOR requires two accounts and a willingness to try to access one account's resources from the other. This test should be part of every feature deployment.

The core argument

The reason IDOR appears so frequently in early stage SaaS applications is that it looks like working code. The endpoint returns the right data, the authentication works, and the feature does what the user expects. The bug is in what happens when a different user makes the same request with a different ID. That scenario does not appear in the happy path test, which is the test most developers run. It takes deliberate adversarial thinking to catch it, and most product engineers are not thinking adversarially when they are focused on shipping features.

The pattern that introduces IDOR is straightforward: an endpoint receives an identifier in the URL or request body, queries the database for the object with that ID, and returns the result. The authentication middleware verifies that the request is authenticated. Nobody writes the authorization check that verifies the object belongs to the authenticated user. This is not negligence; it is a missing step in a process that did not include an authorization checklist. The fix is equally straightforward: every query that retrieves or modifies a resource owned by a user should include the authenticated user's ID as a filter condition. WHERE id = $1 AND user_id = $2 instead of WHERE id = $1.

The multitenant case is where IDOR gets more complex and the consequences of getting it wrong are more severe. In a multitenant SaaS where each customer's data is stored with a tenant_id, an IDOR in a resource owned by a tenant gives one customer access to another customer's data. This is the scenario that ends customer relationships and triggers regulatory notifications. The defense is layered: authorization checks at the application level on every endpoint, row level security policies in the database that enforce tenant isolation, and regular testing from a second tenant account. When I built the data isolation architecture for Velmora, a three layer approach was the standard: middleware that sets the current tenant context, query filters that always include the tenant ID, and RLS policies that enforce isolation even if both upper layers miss a check.

Common mistakes

  1. Assuming authentication implies authorization. Authentication verifies that a request comes from a known user. It says nothing about whether that user has permission to access the specific resource they are requesting. They are separate checks and both must be present.

  2. Relying on UUIDs for security. UUIDs make ID enumeration harder but do not prevent authorization failures. Any system that relies on ID secrecy for security has a broken authorization model.

  3. Not testing cross user access during feature development. Most developers test that their feature works for themselves. Testing that the feature correctly rejects requests from a different user is a separate test that needs to be part of the review process.

  4. Applying authorization checks inconsistently across the API. A codebase where some endpoints check ownership and others do not is a codebase with IDOR vulnerabilities. Authorization checks should be systematic, not applied case by case.

  5. Not auditing bulk operations. Endpoints that accept lists of IDs, such as batch delete or bulk export, need authorization checks on every ID in the list, not just the first one. A bulk operation that authorizes the first ID and then processes the rest without checking is a serious IDOR.

Where to start

  1. Audit every API endpoint that accepts an object ID. For each one, verify that the query includes a user or tenant ownership filter. A code search for your primary resource query patterns will surface the ones that are missing the ownership check.

  2. Write an IDOR test using two accounts for each resource type. Create accounts A and B in your test environment. Log in as A, note the IDs of A's resources. Log in as B and try to access them. Add this test to your test suite to prevent regressions.

  3. Enable row level security for your primary data tables. In Postgres, RLS policies can enforce tenant or user ownership at the database level as a second layer of defense. This catches the cases where application code is incomplete.

FAQ

Frequently asked

  • What does a typical IDOR look like in a SaaS application?
  • Are UUIDs a fix for IDOR?
  • How do I test for IDOR in my own application?
  • What is the difference between IDOR and broken access control?
  • Do row level security policies in the database prevent IDOR?

Author

The person who wrote this

Yashveer Singh wrote this. Class 12, Commerce track, full stack developer. The categories do not align, which is the point. The work runs in production. Everything else is paperwork. If the project on your plate is the one this article describes, you can reach me through the contact page or through Instagram. I will read it. I will reply. That is the standard.

Start the conversation See the work DM on Instagram