Skip to content

GUIDE 04 · WEB APPLICATIONS AND APIs

IDOR and BOLA: test access to another user’s data

An identifier is not an authorization decision. To test object access, use two accounts, known private objects and explicit expected permissions. Confirm that each owner can use its own object and that another identity cannot retrieve the private content, including through exports or downloads.

Scantelio editorial team · Updated

Check user isolation

Sign-in, ownership verification and consent are required. Authorized scenarios, monitoring and CI require Pro or Business.

On this page

Understand IDOR and BOLA

IDOR describes unsafe direct object references; BOLA describes broken object-level authorization in an API. A readable ID is not itself the vulnerability. The issue is a server returning or modifying an object without enforcing the caller’s ownership, organization and role rules.

Prepare two independent contexts

Create A in organization X and B in organization Y, with separate sessions and synthetic documents. Record document paths and unique private markers. First prove that A can read A and B can read B. Otherwise, a forbidden cross-user request could simply reflect invalid sessions or unavailable fixtures.

Primary sources: Primary reference 1 · Primary reference 2

Continue: Prepare an automated API security assessment

Test reads step by step

Request B’s known document using A’s session, then reverse the direction. Inspect private content as well as status. Our controlled fixture returns the other owner’s marker in its vulnerable mode; the fixed mode returns 403 while both owners retain access. The actual BOLA rule confirms the vulnerable observation with repeated reads.

IdentityObjectMethodFixed fixture expectation
Adoc-aGET200
Adoc-bGET403
Bdoc-bGET200
Bdoc-aGET403
guestdoc-aGET200
guestdoc-bGET403
anonymousdoc-aGET401
Adoc-b/downloadGET403
Bdoc-a/downloadGET403
Adoc-a/downloadGET200
Bdoc-b/downloadGET200
anonymousdoc-b/downloadGET401

Check alternate paths to the same object

A protected detail endpoint does not prove that exports, previews and downloads enforce the same permissions. Repeat the known-object test on relevant supported paths. Include guest and anonymous contexts where they have defined permissions. Do not interpret a public resource as private without an explicit expectation.

Reproducible local fixture; synthetic data only.
python3 access-fixture.py
curl -H "X-Fixture-User: a" "http://127.0.0.1:8769/documents/doc-b?mode=vulnerable"
curl -H "X-Fixture-User: a" "http://127.0.0.1:8769/documents/doc-b?mode=fixed"

Primary sources: Primary reference 1 · Primary reference 2

Continue: Supabase security: check RLS and access to data

Check user isolation

Test changes and protected fields

Changing a role, owner or tenant can be more consequential than a read. Define an approved staging mutation, the expected forbidden fields and a way to verify restoration. Do not infer update safety from read controls, and do not perform write checks on production customer objects.

Enforce permissions on the server

Derive identity from a verified session, load trusted object ownership and apply the application’s organization and role rules before returning data or writing changes. A hidden button or client-side condition cannot replace this check. Keep authorization consistent across the main endpoint and secondary access paths.

Primary sources: Primary reference 1 · Primary reference 2

Continue: JWT security: validate tokens and access lifecycle

Prove the fix

The original cross-owner attempt must stop exposing private content, but each owner must still access its own object. A redirect to login, timeout or WAF block is not sufficient proof. Keep the same fixture contract, environment and deployment identifier so the retest compares the intended behavior.

Automate the regression check

Save supported access scenarios in Scantelio and rerun them after releases. Use a targeted retest for a known finding and a broader release check for the rest of the approved coverage. Review the report when roles, organizations, object paths or fixture markers change.

Continue: Add security checks to CI/CD and GitHub Actions

Reproducible examples and downloads

Tested with: guides-1 · Python 3.13.0 · PyJWT 2.15.1

All example data is synthetic. Downloads contain no active keys or customer records. Run examples only in your own isolated test environment.

Example verification record: versions, actions and observations

Actual Scantelio evidence panel displaying the controlled fixture result; this is not a customer scan or a full end-to-end scan
Actual Scantelio evidence panel displaying the controlled fixture result; this is not a customer scan or a full end-to-end scan. Test fixture, synthetic data.

Questions and answers

Are UUIDs enough to prevent IDOR?

No. Hard-to-guess IDs reduce discoverability but do not enforce permissions.

Does a 403 prove the entire API is safe?

It proves only that response under those conditions. Verify legitimate controls and relevant alternate routes.

Can tenant isolation be tested?

Yes, with independent tenant identities, known fixtures and explicit expected denial.

Must every cross-user request fail?

No. Some resources are intentionally shared. Expected access must reflect the product’s rules.

Can downloads leak an otherwise protected object?

Yes. Test the known object through relevant export and download paths too.

What should an inconclusive retest mean?

The available evidence cannot establish whether the issue was fixed; do not label it resolved.

Editorial team and sources

Scantelio editorial team: methodology and limitations. Example verified: 2026-11-02.

Apply the check to your own project

Check user isolation

Choose your project after signing in. No scan runs without verification and consent.