Vulnerability guide

IDOR vulnerability

Learn what IDOR is, how insecure direct object references expose data, where object-level authorization fails, and how to prevent IDOR and BOLA in web applications and APIs.

Access controlAPI securityCWE-639Prevention guide

What IDOR is

Insecure direct object reference, commonly shortened to IDOR, is an access control vulnerability where an application exposes a direct reference to an object and then trusts the client to choose which object should be opened, changed, downloaded, or deleted.

The reference can be a user ID, invoice ID, document name, order number, account UUID, tenant key, export token, or another value that points to a real record or file. The security failure is not the presence of an identifier by itself. The failure is missing server-side authorization for the specific object being requested.

IDOR is closely related to broken object level authorization, or BOLA, in API security. Both describe the same core mistake: authentication proves who the caller is, but the application does not verify whether that caller is allowed to act on the referenced object.

How IDOR works

Most applications need object identifiers to load profiles, invoices, projects, messages, exports, and support tickets. IDOR appears when the backend accepts one of those identifiers from the request and retrieves the object without scoping the lookup to the current user, role, tenant, or policy.

This can happen even when the user is logged in, the ID is hidden in a form field, the route is protected, or the identifier is a long UUID. If a valid reference leaks through a link, API response, mobile app, log, shared document, or browser history, an authorization check must still block unauthorized access.

The safer pattern is to make every object read or write prove both identity and permission at the server boundary or data access layer. The request may provide an object ID, but the server decides whether the current principal can use that object in that action.

Unsafe pattern
app.get('/api/invoices/:invoiceId', requireLogin, async (req, res) => {
  const invoice = await db.invoices.findById(req.params.invoiceId)
  res.json(invoice)
})

The route is authenticated, but the object lookup trusts the requested invoice ID and searches all invoices.

Safer pattern
app.get('/api/invoices/:invoiceId', requireLogin, async (req, res) => {
  const invoice = await db.invoices.findFirst({
    where: {
      id: req.params.invoiceId,
      tenantId: req.user.tenantId
    }
  })

  if (!invoice)
    return res.status(404).json({ error: 'Not found' })

  res.json(invoice)
})

The lookup is scoped to the authenticated tenant before returning the object, so another tenant's invoice is not reachable through the same endpoint.

Why IDOR matters

IDOR can turn a single missing authorization check into unauthorized access across many records because modern web applications and APIs expose object references throughout account flows, mobile clients, dashboards, exports, and integrations.

The business impact depends on the object. A vulnerable endpoint that reads public metadata is different from one that exposes health data, invoices, API keys, admin actions, or cross-tenant records, but both point to the same design problem.

Confidentiality loss

Attackers may read profiles, invoices, tickets, files, messages, exports, tokens, or other data that belongs to another user or organization.

Integrity damage

Unsafe object writes can let users change another account's settings, documents, permissions, order details, or workflow state.

Tenant isolation failure

In SaaS products, IDOR can break the boundary between customers and expose records across workspaces, teams, or organizations.

Account and workflow abuse

Weak authorization around reset flows, invitations, support tools, or payment objects can enable unauthorized actions that look legitimate.

Compliance and trust impact

Exposure of personal, financial, health, or business records can trigger disclosure duties, contractual issues, and long-term reputation loss.

API abuse at scale

Automated clients can repeat object-level authorization failures quickly when APIs accept predictable or leaked object references.

Common forms of IDOR

IDOR does not belong to one framework, language, or URL shape. It appears wherever a request-controlled reference is used to reach an object without a matching authorization decision.

FormWhat to understand
Path or query IDORA route or query parameter identifies a profile, invoice, project, order, or message, and the backend returns it without checking ownership or permission.
Request body IDORA JSON field, form input, hidden field, GraphQL variable, or mobile API body contains an object ID that the server trusts.
File reference IDORDownload links, generated reports, transcripts, attachments, or exports are addressed by names or keys that do not enforce access checks.
Multi-tenant IDORA SaaS endpoint filters by object ID but forgets to include workspace, account, organization, or tenant scope in the lookup.
UUID or leaked-reference IDORThe object identifier is hard to guess, but the application still fails if a user can obtain or reuse another valid reference.
Workflow-step IDORA later step in an approval, invite, checkout, reset, or support process trusts an object selected in an earlier step.
Broken object level authorizationAn API exposes object operations without checking whether the authenticated caller can read, update, delete, or act on that exact object.

Where IDOR appears

Teams often review obvious account pages first, but IDOR can hide anywhere object identifiers cross a client boundary. Treat every object reference from a request, stored client state, or integration as untrusted until the server proves authorization.

  • User profiles, account settings, billing records, invoices, orders, subscriptions, and payment objects.
  • Project, workspace, organization, tenant, repository, document, support ticket, and message endpoints.
  • File downloads, generated PDFs, exports, backups, thumbnails, transcripts, and attachments.
  • API route parameters, request bodies, GraphQL variables, mobile app calls, and background sync endpoints.
  • Cookies, headers, local storage values, hidden form fields, redirect targets, and invite tokens.
  • Admin panels, customer support consoles, data import jobs, approval flows, and multi-step workflows.
  • Webhooks, partner integrations, shared links, audit logs, and stored references reused later by the application.

How to prevent IDOR

The durable fix for IDOR is object-level authorization. Every request that reads, changes, deletes, exports, or links an object should verify that the current principal is allowed to perform that specific action on that specific object.

Non-sequential identifiers, rate limits, and monitoring are useful defense-in-depth controls, but they do not replace authorization. If the server would return the wrong object when given a valid reference, the application is still vulnerable.

Enforce object-level authorization

Check permission for every object access, not just the route. Authentication confirms identity; authorization confirms whether that identity can use the referenced object.

Scope data queries to the caller

Fetch records through the current user's allowed dataset, tenant, organization, role, or policy context instead of searching the whole table first.

Centralize authorization policy

Put ownership, role, tenant, and workflow rules in a shared policy layer so controllers, APIs, workers, and admin tools cannot silently diverge.

Treat identifiers as untrusted input

Validate format and existence, but never treat possession of an ID, UUID, filename, or token-like reference as proof of access.

Use hard-to-enumerate IDs carefully

Random IDs and UUIDs reduce guessing and record-count leakage, but they are defense in depth. They must sit behind authorization checks.

Protect files and generated exports

Serve sensitive files through authorized application handlers or short-lived signed access patterns, not permanently exposed static paths.

Monitor enumeration behavior

Log denied object access, unusual ID patterns, high-volume misses, cross-tenant attempts, and repeated object probing so abuse is visible.

Detection and response

IDOR testing should only be performed on systems you own or are explicitly authorized to assess. Effective testing usually combines design review, code review, paired-account checks, API testing, and runtime telemetry.

  1. 1

    Map objects and permissions

    Inventory sensitive object types, who should access them, which actions are allowed, and where each object ID appears in web, API, mobile, worker, and admin flows.

  2. 2

    Test with paired accounts

    Use two or more authorized test accounts with different roles, tenants, and ownership boundaries to confirm that object references cannot cross the expected boundary.

  3. 3

    Review code and data access

    Look for find-by-ID calls, unscoped queries, raw repository helpers, hidden form IDs, file downloads, and APIs that authorize the route but not the object.

  4. 4

    Exercise APIs safely

    Combine DAST, API contract tests, SAST, manual review, and automated authorization tests in controlled environments where testing is permitted.

  5. 5

    Watch runtime signals

    Monitor denied access, repeated missing IDs, unusual sequence walks, cross-tenant object attempts, support-tool anomalies, and export/download spikes.

  6. 6

    Patch and retest

    Add object-level checks, update tests for the affected path, review adjacent endpoints, rotate exposed secrets when needed, and retest with the original evidence.

Developer checklist

Use this checklist when reviewing a feature that accepts object identifiers from a browser, mobile client, API consumer, integration, or stored workflow.

  • Every object read, update, delete, export, or action has a server-side authorization decision.
  • Data queries are scoped to the current user, tenant, workspace, organization, or policy context before returning results.
  • Hidden fields, cookies, headers, route params, request bodies, and GraphQL variables are treated as attacker-controlled.
  • Admin, support, worker, import, webhook, and export paths enforce the same object rules as user-facing endpoints.
  • UUIDs or random IDs are used only as defense in depth, not as the primary access control.
  • Sensitive files are served through authorization-aware handlers or short-lived access mechanisms.
  • Automated tests include same-role, cross-role, same-tenant, cross-tenant, owner, and non-owner cases.
  • Logs capture denied object access and suspicious enumeration patterns without exposing sensitive data.
  • Findings are triaged for data exposure, remediated at the policy or query layer, and retested before closure.

IDOR FAQ

What is an IDOR vulnerability?

IDOR is an access control flaw where an application uses a client-supplied object reference, such as an ID or filename, without verifying that the current user is allowed to access that exact object.

Is IDOR the same as BOLA?

They overlap heavily. IDOR is the traditional web application term, while BOLA is common in API security and focuses on broken authorization for individual objects.

Do UUIDs prevent IDOR?

UUIDs can make object references harder to guess, but they do not prove authorization. If a user can obtain another valid UUID and the server returns the object, the access control problem remains.

What is the best way to prevent IDOR?

Enforce object-level authorization on the server for every read, write, delete, export, and workflow action, and scope data access to the current user's allowed objects.

How should teams test for IDOR safely?

Test only with authorization, usually with paired accounts across different users, roles, and tenants, then verify that every object reference is blocked unless the caller has explicit permission.

References and further reading

This guide summarizes established IDOR, broken access control, and object-level authorization guidance in Splorix's own wording. Use the original references for deeper technical detail and secure development policy.