Skip to content

Test Cross-Tenant Object Reads Safely

Use synthetic records to verify that object reads enforce tenant ownership.

A record ID is a locator, not permission. An API can accept a valid ID and still need to decide whether the current caller may read that object. OWASP names this failure class Broken Object Level Authorization. Test it with accounts and records that your team owns, or within a written scope that permits the exact checks.

A two-tenant read fixture

Create Tenant A and Tenant B in staging. Give each a member account and a record with a distinct non-sensitive marker. Keep the IDs and marker values in a private test manifest.

CallerRequested recordExpected result
A memberA private recordOnly A's approved fields
A memberB private recordDenial with no B data
B memberA private recordDenial with no A data
Anonymous callerA private recordAuthentication denial
A member after removalA private recordDenial after revocation takes effect

Run the same table against direct detail routes, nested resources, GraphQL node lookups, and any alternate API version that reads the record. Do not assume a list endpoint and a detail endpoint share the same policy. A UI hiding a link is not an access check.

Record the build identifier, synthetic account role, route, expected decision, actual status, and whether the response or logs exposed a marker. For denied calls, inspect side effects only in the owned environment. A 404 can be a deliberate concealment choice, but the important fact is that no unauthorized data was returned.

A useful regression test binds the lookup to the authenticated tenant or evaluates an explicit owner rule before serialization. Then it checks permitted access as well as denial; a route that rejects everyone is broken too. OWASP's authorization regression guide supports this positive-and-negative approach.

What does the denial prove?

Illustrative assertion for GET /v1/records/B7 as A: the response contains no B-marker, title, owner email, or nested attachment URL, regardless of whether policy selects 403 or concealed 404. Repeat through the nested route /v1/projects/B/records/B7. As B, the same B7 fixture returns the approved fields. Record the route version and exact keys for both cases; replace these example paths with the product's routes.

This fixture establishes one behavior for one build. It does not prove all tenant boundaries are safe. If ownership is unclear, stop and update the boundary map before broadening the test.

Find the gaps in your access controls

See how an illustrative cross-workspace finding connects evidence, impact and a fix. Discuss the tenant boundaries your team needs reviewed.

Sources

  1. OWASP API Security Top 10 (2023)Accessed
  2. OWASP Authorization Regression Testing Cheat SheetAccessed