A SaaS application can enforce permissions on its main record page and still expose the same data through search, exports, a file link, or a background job. Tenant-isolation testing needs to follow the record through those paths and include both legitimate access and requests that should fail.
This matrix gives application teams eighteen original cases with a positive control, a negative control, and an observable result. Adapt it to your product’s permission model and run it only on systems and records you are authorized to assess. The worksheet includes an evidence log and a synthetic fixture plan.
1. Prepare identities, tenants, and synthetic records
Create tenant A and tenant B with deliberately distinct records. In A, provide an owner, a member, and a read-only role if the product supports one. In B, provide an owner and another ordinary user. Add a user who belongs to both tenants so tests can distinguish a valid organization switch from unauthorized access.
Give synthetic records unique markers and known IDs. Include an invoice, draft, project, file, export, and event appropriate to the application. Known IDs let you test the authorization decision directly. Random identifiers alone cannot establish whether the server checks ownership.
Write the expected permission rules before testing. Some products intentionally share records, let support staff impersonate users, or issue bearer download links that work until expiry. Document those policies and their limits so your results measure the actual boundary rather than an unstated assumption.
2. Exercise each delivery and change path
The positive control should work under an authorized identity. The negative control changes the principal, tenant, object relationship, role, or permission state. Keep other conditions as similar as possible so the result answers a specific authorization question.
For each applicable API format, test the same underlying boundary through the interfaces your product actually exposes. Include REST or GraphQL requests, file delivery, background jobs, integration keys, and realtime channels where present. Mark absent features as not applicable with a reason.
| Case | Positive control | Negative control | Required observation |
|---|---|---|---|
| TEN-01 · Direct read | Member A reads an owned synthetic invoice. | Member A requests tenant B’s invoice using its known test ID. | No B data or unauthorized metadata is returned. |
| TEN-02 · Direct update | Editor A updates an owned test draft. | Editor A targets tenant B’s draft with the same request format. | B’s record and audit history show no unauthorized change. |
| TEN-03 · Delete | Owner A deletes a disposable owned record. | Owner A targets a disposable record belonging to B. | B’s record remains and no deletion job is scheduled. |
| TEN-04 · List and search | Member A finds its own synthetic marker. | Member A searches for a unique marker placed only in B. | Results, counts, facets, and suggestions reveal no B content. |
| TEN-05 · Bulk operations | Editor A updates two owned test records. | Editor A submits a mixed list containing one B-owned record. | The documented partial or atomic policy protects B; no hidden partial update occurs. |
| TEN-06 · Tenant selector | A user selects an organization they belong to. | The user supplies B’s tenant ID in each accepted selector. | The server derives or verifies membership before accessing B. |
| TEN-07 · Fields and roles | An ordinary member edits a permitted profile field. | The same member submits an owner role or billing-owner field. | Privileged fields stay unchanged and the response discloses no protected field. |
| TEN-08 · Nested records | Member A opens a file in an owned project. | Member A combines an A project ID with a B file ID. | Both the parent and child relationship are checked. |
| TEN-09 · Downloads | Member A opens an authorized test export. | Member B attempts the same protected download through each delivery route. | Access follows the documented file-link model and expiration policy. |
| TEN-10 · Export creation | Member A starts an export for its organization. | Member A requests an export scoped to B or includes B’s record IDs. | No B data enters the job, file, notification, or response. |
| TEN-11 · Queued permissions | A permitted member collects a completed export. | Remove that member’s access between job creation and collection. | Job execution and delivery honor the documented revocation policy. |
| TEN-12 · Invitations | Owner A invites a synthetic user into A. | Member A changes an invite’s tenant or role to gain access to B. | Invitation issuance and acceptance enforce the intended tenant and role. |
| TEN-13 · User in two tenants | A user with memberships in A and B selects each explicitly. | Remove only B membership, then reuse an old B request. | A access remains valid while B access is denied. |
| TEN-14 · API credentials | A test integration key reads its permitted A records. | The A key requests B resources or a disallowed operation. | Tenant and action restrictions hold independently of the browser session. |
| TEN-15 · Webhooks | A test event reaches A’s approved receiver. | A user attempts to subscribe to B’s events or redirect B’s delivery. | No B event body or signing material reaches A’s receiver. |
| TEN-16 · Cache separation | A and B receive their own versions of the same route. | Fetch A’s response, then request that route as B and anonymously. | No cached A body is served to another principal. |
| TEN-17 · Realtime channels | Member A subscribes to an owned test project. | Member A joins B’s channel or keeps a channel after revocation. | Subscription and ongoing delivery respect the documented access policy. |
| TEN-18 · Support access | An authorized support action produces a visible audit event. | An ordinary user or expired support session repeats the support action. | Only the authorized support scope works and its actor is attributable. |
3. Verify response content and final state
Retain a sanitized request and response, actor, active tenant, target owner, timestamp, application build, and final record or job state. For a denied write, confirm that no later worker performs it. For a read, inspect the body and metadata as well as the status code.
A 403 response can still include private data in a response body. A 200 response may correctly return an empty result. The assessment should establish whether information crossed the boundary or an action occurred, with the expected behavior defined for that endpoint.
Use the worksheet’s result labels consistently: passed under tested conditions, failed, blocked, or not applicable. Missing credentials, unavailable logs, and unreachable staging services are coverage gaps. They should not enter a passing-test denominator.
4. Worked example: export access after membership removal
In a synthetic test, member A starts an export while authorized. The job produces a file later. Before collection, the test owner removes that member from A. Test the job status endpoint, notification link, application download route, and any storage link the product issued.
Suppose the application route now denies access but a previously issued bearer URL still works. Record its expiry, the information it exposes, and whether that behavior matches the approved revocation policy. Immediate revocation may require a different delivery design; the existence of a signed URL alone does not establish either a pass or a failure.
Retest the intended policy after remediation. Also verify that a member who retains access can still collect an authorized export. This example illustrates an assessment method and does not describe an observed customer incident.
5. Turn verified failures into regression tests
Start with the smallest reproducible case that shows an unauthorized outcome. Keep the authorized comparison and a stable fixture relationship so future runs do not pass because the target record disappeared. Ensure cleanup removes only the disposable data created for the test.
Put checks at the service boundary where authorization is enforced, then cover the public route that exposed the issue. A UI test hiding a button cannot establish that an API refuses the same operation. Include queued and integration paths in the regression set when they can reach the same records.
Revisit the matrix when introducing a new role, adding tenant switching, changing caches, or moving downloads to another service. Link the case IDs to verified findings and retest results so the engineering owner can trace what changed. The scope template helps agree coverage and access for an independent assessment.
6. Report what the matrix establishes
An eighteen-row worksheet is a starting set, not proof that every permission is correct. Report the features, roles, endpoints, deployment, and data relationships tested. Identify alternate routes and environments that were excluded or blocked, and distinguish synthetic demonstrations from production incidents.
Prioritize verified unauthorized reads and changes using the sensitivity, business effect, and realistic access involved. Keep an owner and retest condition for each fix. For assistance with a scoped assessment of web applications and APIs, discuss your environment with Ceron.
References and reuse
The OWASP Authorization Cheat Sheet explains authorization controls and testing principles. OWASP ASVS provides versioned verification requirements. The cases here are original operational examples and do not constitute an official OWASP checklist or certification.
The original Ceron worksheet and test cases on this page are available under CC BY 4.0. You may adapt them with attribution to Ceron, a link to this resource, and an indication of changes. The license applies to this resource’s original worksheet and cases, not third-party standards, Ceron branding, or other site content. The scenarios are illustrative and contain no customer results.