CriticalSecurityAuto-fixable

IDOR Vulnerability on REST Endpoint

A REST endpoint returns resources by id without verifying the caller owns that resource. Any authenticated user can access any other user's data by changing the id in the URL.

Typical error

Resource accessible via id change without ownership check

What this is

Insecure Direct Object Reference (IDOR) is the "change a number in the URL, see someone else's stuff" bug. A typical AI-generated endpoint:

// GET /api/invoices/[id]
export async function GET(
  _req: Request,
  { params }: { params: Promise<{ id: string }> }
) {
  const { id } = await params
  const invoice = await db.invoice.findUnique({ where: { id } })
  return Response.json(invoice)
}

Any logged-in user can fetch /api/invoices/123, then /api/invoices/124, etc., and see every invoice in the system.

Why AI tools ship this

Scaffold tools generate CRUD endpoints that match the database schema. They authenticate the request (is the user logged in?) but skip authorization (does this user own this specific row?).

How to detect

Audit every dynamic API route. For each, answer:

  1. Does the resource belong to a user?
  2. Does the handler verify req.user.id matches the owner?
  3. If ownership is enforced only in the database, is RLS actually enabled?

How to fix

Three options, from weakest to strongest:

  1. App-level ownership check

    const invoice = await db.invoice.findUnique({ where: { id } })
    if (!invoice || invoice.userId !== session.userId) {
      return new Response('Not found', { status: 404 })
    }
  2. Scoped query (preferred)

    const invoice = await db.invoice.findFirst({
      where: { id, userId: session.userId },
    })
  3. Database-level policy (most robust)

    Enable row level security so the database itself filters on auth.uid() = owner_id. No app-level bug can bypass it.

Always return 404 on ownership mismatch, not 403. A 403 reveals that the resource exists.

Commonly affected tools

Glossary

Is your app affected?

FinishKit checks for this finding and 50+ more across 8 dimensions of production readiness. Free during beta.

Scan your app