Design Synthetic Tenant Test Fixtures
Build safe test records that reveal both cross-tenant leaks and false denials.
Real customer data is not needed to test a tenant boundary. Synthetic records can make a leak easier to see and easier to clean up. The fixture should include both prohibited and legitimate access. Otherwise a blanket denial can look like a security success. The OWASP Authorization Regression Testing Cheat Sheet supports explicit positive and negative cases.
Fixture schema
| Record or identity | Purpose |
|---|---|
| Tenant A and B | Separate ownership |
| A and B private records | Cross-tenant denial |
| Public record | Legitimate anonymous read |
| Shared record with explicit grant | Intentional collaboration |
| A member and admin | Role distinction |
| Former A member | Revocation |
| Service account | Background-job context |
Use harmless marker strings that identify the owner without resembling real names or secrets. Give each record a stable fixture ID and cleanup rule. If the database enforces global unique IDs, do not force a collision that production cannot represent; create overlapping local IDs only when the schema permits them.
Test what the fixture can prove
Record expected read, write, export, and notification outcomes for each identity. Reset state between mutation cases. Run the suite after a fresh database seed and after role changes, because stale sessions and caches can alter results. Confirm that a B record never appears in A's list, count, search, cache, or export. Confirm A still gets the data it should.
The OWASP Multi Tenant Security Cheat Sheet frames isolation across shared resources. This fixture is the reusable evidence base for those paths. It does not establish customer authorization or coverage of an unknown route. Keep a fixture manifest with build, schema version, owner, and teardown result. If a test requires production data to be meaningful, first ask why the synthetic model is insufficient and handle that as a separate review gate.
Illustrative fixture rows: A-private is readable by A only; B-private by B only; public-1 is readable anonymously but not editable anonymously; A-shared-with-B is readable by the named B member but not by an unrelated B member. Assert the returned fields for each allowed read and no write effect for each denied action. A blanket cross-tenant deny would fail the shared-record positive case.
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.