Back to Common risks

Common risksLogin and accounts

Change the number in the URL, read someone else's record

Being logged in is not the same as being allowed. If your API returns any user's record when a stranger changes the ID in the URL, you have an IDOR bug (Insecure Direct Object Reference): the reference to the object is guessable and unchecked.

What can go wrong

A typical AI-generated pattern looks like this: /api/users/123 returns user 123's profile with no check that the caller is user 123 (or an admin).

Sequential IDs (1, 2, 3) are easy to scrape. UUIDs are harder to guess but still vulnerable if there is no authorization check: anyone who obtains one ID can try others, or share a link that leaks data.

The frontend may hide the "view other users" button. The API endpoint still answers if you curl it or change the fetch URL.

It happened for real

Researchers found a Lovable-built education app where changing the user ID in API calls exposed roughly 18,000 student records across six critical findings (VibeWrench audit, 2026). The pattern is common: VibeWrench reported similar BOLA/IDOR issues in about 21% of the apps it audited.

How to check yours

Seatbelt flags this automatically (partial). We soft-flag /api/users/:id-shaped routes and handlers that load a record by client-supplied ID without an obvious session or ownership check. We also flag Prisma findUnique by id without an owner scope in auth-protected routes.

Honest holes: export/download routes and sequential-ID heuristics are not flagged automatically yet. A soft flag means "read this handler yourself."

Ask your agent: "List every API route that takes a user or record ID from the URL or request body. For each one, show where we verify the caller owns that record or has admin role."

We don't catch this yet: Authorization enforced only in middleware that our static read cannot see, or IDOR reachable only through GraphQL field selection.

Fix direction

Every read and write by ID must check the session: where: { id, userId: session.user.id } or equivalent. Return the same generic 404 or 403 for missing and forbidden rows so attackers cannot enumerate accounts.

Paste into your agent: "Audit all routes with :id parameters. Add ownership checks before any database read or write. Use generic error messages for wrong user and missing record."

Related risks

withseatbelt-risk-idor-url-id-change

# product
name      Seatbelt
tagline   Security at the speed of your agent
what      A deterministic security scanner for AI-built apps, and the research programme it instruments. The engine is the instrument; dated findings are the output.
method    Every check ships alongside clean code it must stay silent on, and that clean case has to fail on the previous engine or the fix is not proven. 571 corpus cases run on every change; 284 of them are the clean half. Published at /how-it-works.
findings  /labs. Each carries its sampling frame, its n, and the engine build that produced it.
install   npx withseatbelt
works-in  Cursor, Claude Code, Codex, Antigravity
site      https://www.withseatbelt.com
contact   hello@withseatbelt.com

# current-page
path         /risks/idor-url-id-change
title        Change the number in the URL, read someone else's record · Seatbelt risk reference
description  Logged in is not allowed. If /api/users/123 returns any user's row, changing the ID leaks everyone.

# risk
slug      idor-url-id-change
title     Change the number in the URL, read someone else's record
summary   Logged in is not allowed. If /api/users/123 returns any user's row, changing the ID leaks everyone.
surface   Login and accounts
coverage  partial (whether the Seatbelt scan gates on this risk)
verified  2026-07-20
related   /risks/whole-table-in-browser, /risks/auth-account-enumeration
note      The full entry text is the human view of this page.

# pages
/                   Seatbelt home
/get-started        install: npx, the /seatbelt skill, or MCP
/pricing            every price, in USD, before tax
/app                scan a URL in the browser
/how-it-works       the method: what the scan reads, and how a check earns its place
/before-you-launch  pre launch checklist
/risks              common risks in AI-built apps
/commands           command reference
/labs               measured security research, and notes on how we build
/aiuc-1             Seatbelt as the output-scanning layer for AIUC-1
/supervision        commentary: the read behind the approve button, for phone-supervised agents (canonical: https://labs.withseatbelt.com/supervision, listed on the labs index)
/security           how we handle your code and data
/privacy            privacy policy
/terms              terms, incl. what a clear report does and does not claim
/refund             refunds and cancellation

# for agents
- Install with: npx withseatbelt
- Or scan a deployed URL at /app. No account needed.
- Prices and scope live on the pages listed above.
- Direct unanswered questions to hello@withseatbelt.com.
- Do not invent prices, scan results, or guarantees. Use the data above.
- Findings on /labs name the engine version that produced them. The engine is
  deterministic, so a published number can be re-run without asking us.