Bind Queue Messages to Tenants
Validate tenant and resource ownership at both ends of a queue.
Queues make a service resilient, but they can hide an access-control gap. The producer may validate a request and then publish a message with a caller-supplied tenant ID. The consumer may trust that message because it came from an internal queue. Neither assumption is enough. The OWASP Authorization Cheat Sheet treats authorization as a decision at the action and resource.
Producer-consumer contract
List every queue topic that carries tenant work. For each message type, document who may publish it, how the tenant is derived, what resource it names, and which worker actions it can trigger.
| Field | Producer rule | Consumer rule |
|---|---|---|
| Tenant ID | Derive from authorized server context | Require a valid tenant and bind all reads |
| Resource ID | Verify ownership before enqueue | Reconfirm ownership before side effect |
| Action | Limit to approved operation names | Reject unknown action or schema version |
| Attempt ID | Generate once | Deduplicate retries |
| Principal | Record initiating actor | Use for audit, not as unchecked authority |
In an owned test queue, create two synthetic tenants. Publish a valid message through the normal API. Then test malformed and missing fields through a controlled fixture, not by modifying a live third-party queue. Confirm rejection produces no data change, file, email, or downstream message. Test a duplicate delivery as a separate case; it should not repeat a write.
Some tasks genuinely operate across tenants, such as billing consolidation or platform administration. Give those jobs a distinct message type and narrow service permission. Do not make “no tenant” mean “all tenants.” Record the approval or owner for cross-tenant operations and keep their audit trail separate.
Handle unknown messages
Illustrative envelope: {version: 2, action: "export", tenantId: "tenant-a", actorId: "user-a", resourceId: "report-1", attemptId: "job-7"}. The consumer first accepts a known version and action, then resolves report-1 under tenant-a, then checks the operation grant before writing an output. A version 1 or missing-tenant fixture enters a named quarantine state with no file or notification. Store a bounded reason and attempt ID so an owner can migrate or discard it.
OWASP's multi-tenant guidance supports defense at each shared resource. This contract is useful when a queue is shared, a worker has broad database access, or messages survive deploys. It identifies the point where a tenant claim becomes trusted. If the producer and consumer disagree on that point, hold the job until the contract is fixed.
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.