5 min read

Insecure Direct Object Reference (IDOR) — what it is and how to prevent it

IDOR is the classic name for an authorization bug where a user can change an ID in a URL and access data they should not see. It is BOLA's older cousin and still ships in half of all new apps.

IDOR is a twenty-year-old vulnerability class that is shipping in more new apps today than ever before — because AI coding assistants produce it by default. This guide explains what IDOR is, why it keeps reappearing, and how to stop it with a combination of database-level and API-level controls.

What it is

An Insecure Direct Object Reference occurs when an application exposes a reference to an internal object (a database row, a file path, a tenant identifier) and relies on obscurity or client-side controls to prevent unauthorized access. When the reference is sent over the wire and the server does not re-authorize the access, the reference can be substituted by an attacker.

Vulnerable example

// Vulnerable: uses client-supplied user_id
export async function GET(req: Request) {
  const url = new URL(req.url);
  const userId = url.searchParams.get("user_id"); // <-- attacker-controlled
  const user = await db.user.findUnique({ where: { id: userId! } });
  return Response.json(user);
}

Fixed example

// Fixed: use session-derived identity, ignore client-supplied IDs for "me" endpoints
import { auth } from "@/lib/auth";

export async function GET() {
  const session = await auth();
  if (!session?.user?.id) return new Response(null, { status: 401 });
  const user = await db.user.findUnique({ where: { id: session.user.id } });
  return Response.json(user);
}

How Securie catches it

Securie's IDOR specialist walks every route and identifies parameters that control access to persisted objects. Then the verification sandbox submits requests with substituted identifiers from fixtures representing different users. A confirmed data leak becomes a finding; the patch rewrites the route to use session-derived identity where appropriate.

Checklist

  • Never trust client-supplied IDs as the sole basis for authorization
  • Prefer session-derived identity for 'me' endpoints (`/api/me/orders`, not `/api/orders?user=X`)
  • Pair API-layer authz with database RLS — defense in depth
  • Normalize error responses — do not leak existence through 404 vs 403 differences
  • Audit-log every access to sensitive objects

FAQ

Is IDOR the same as BOLA?

They are the same class of bug with different names. OWASP API Security adopted BOLA; OWASP Web Top 10 used IDOR. Securie treats them as one specialist category.