Protect Tenant Pagination Cursors
Bind a pagination cursor to the tenant, filter, and permission context that issued it.
A cursor can carry a database position, sort key, or encoded filter. If it can be reused under another tenant, a client may skip into rows it could not reach through a fresh query. Treat the cursor as untrusted input and bind it to the authorized query that issued it. OWASP Multi Tenant Security applies to collection paths as well as detail records.
Cursor claim contract
| Claim or stored field | Purpose |
|---|---|
| Tenant identity | Prevent cross-tenant reuse |
| Query/filter digest | Keep cursor on the original result set |
| Sort key and direction | Preserve deterministic paging |
| Issue time or version | Limit stale cursor behavior |
| Policy context | Recheck permission after role change |
| Integrity protection | Detect client modification |
A cursor need not expose these fields to the client. It can be an opaque server-side ID. If it is self-contained, protect its integrity and avoid storing private values in readable form. The server still needs current authorization when the cursor is used.
Exercise the edge cases
Create synthetic A and B lists. Request an A page and save its cursor. Use it as B, change the filter, remove A membership, and replay it after a data update. Confirm no B or A private data crosses the boundary. Test both forward and reverse paging if supported. Compare counts and facets, because they can leak even when rows are correctly scoped.
The OWASP Authorization Cheat Sheet supports resource-level checks. The artifact is a cursor contract plus negative tests. It should live next to the list endpoint specification. A signed cursor only proves it was issued by the server; it does not prove the current caller is still allowed to use it. Keep the checks in owned or explicitly authorized systems.
Illustrative cursor claim set: tenant=A, filterDigest=F1, sort=createdAt-desc, position=P7, issuedPolicyVersion=4, integrityTag=server-issued. Reuse it as B or with filter F2. Expected result: a controlled invalid-cursor response, no rows, no count from A, and no side effect. Reuse after A membership removal must also fail current authorization even if its integrity tag remains valid. An opaque server-side cursor can store the same binding outside the token.
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.