Safeguard
Security Guides•

Do random UUIDs stop IDOR and BOLA in an API?

Random IDs make records harder to guess, but they do not fix broken object level authorization. Learn why the ownership check is still required.

Safeguard Security Team
3 min read

No. Random UUIDs make record IDs harder to guess, which OWASP recommends, but they do not fix broken object level authorization. If the server never checks that the caller may access that record, anyone who obtains a valid ID can read it. The ownership check is the control.

Definitions

IDOR (insecure direct object reference) and BOLA (broken object level authorization, API1:2023) describe the same flaw: the server trusts an ID from the client without confirming the caller is allowed to use it. OWASP notes the ID can be an integer, a UUID or a string, and can appear in the path, query string, headers or body.

What OWASP says

OWASP's prevention list for API1 has two separate points. First, check on every function that uses client input to reach a record whether the logged in user may perform that action on it. Second, prefer random and unpredictable values as GUIDs for record IDs. The second is a hardening step. The first is the fix. OWASP also says that comparing the session user ID to the ID parameter covers only a small subset of cases.

Why random IDs are not enough

SituationWhat happens
Sequential integer IDs, no checkAttacker counts up and reads everything
Random UUIDs, no checkAttacker needs one valid ID, then reads that record
Random UUIDs, with checkValid ID from another user is refused

IDs leak more often than teams expect:

  • list endpoints that return other people's IDs
  • IDs in shared links, emails and screenshots
  • IDs in logs, analytics and error messages
  • IDs known to former employees, partners or other tenants

Once an ID is known, only the authorization check stops access.

A quick worked example

User A creates an invoice and gets back a random ID. User A pastes the link into a support chat, and the ID lands in the chat history and a screenshot. Now a support contractor, or anyone who later sees that transcript, holds a valid ID. If the invoice endpoint checks only that the token is valid, that person can fetch the invoice. If it checks that the caller owns the invoice, or belongs to a role allowed to see it, the request fails. The ID format was never the deciding factor.

What to do

  1. Enforce ownership or role policy in one shared layer that every handler calls.
  2. Deny by default, as OWASP advises for function level checks.
  3. Use random identifiers for new records, from a cryptographically secure generator, as defence in depth.
  4. Write tests with two users: user A creates a record, user B requests it, expect a refusal.
  5. Run those tests in CI and block merges that fail, as OWASP recommends.

See how to test for BOLA with two accounts for the steps.

Quick check

Should I switch from integer IDs to UUIDs?

It is a sensible hardening step for new records, but do not treat it as the fix. Add the authorization check first.

Which status code should a refused request return?

403 states the caller is not permitted. Some teams return 404 to avoid confirming a record exists. Pick one, apply it consistently, and test it.

Safeguard provides policies and gates for enforcing checks in pull requests, and a free scan at gold.safeguard.sh/scan.

Sources

Last reviewed: 19 October 2026.

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.

Self-healing security runs on Safeguard.

Your first fix PR is minutes away.

No sales call required, even your agent can complete the purchase over MCP.