No. A tenant prefix in an object key organizes files and makes policies easier to write, but naming is not authorization. Authorize the exact object and operation for the verified tenant before serving it or creating a signed URL, then use the prefix as an extra boundary.
What a prefix does and does not do
The OWASP Multi-Tenant Security Cheat Sheet recommends partitioning tenant-scoped objects with a tenant-aware key, bucket, account or enforceable storage policy. It also states that naming is not authorization. A key like tenants/acme/report.pdf only helps if every code path that builds or accepts a key checks who is asking.
If a handler takes a file path from the client and glues it to a prefix, an attacker may try path tricks or simply name another tenant.
Three layers to combine
| Layer | Purpose |
|---|---|
| Authorize before access | Check the caller may perform this operation on this object |
| Tenant-aware key, bucket or policy | Limit blast radius if a check is wrong |
| Signed URL limits | Narrow what a leaked link can do |
Validate what goes into the key
The sheet's sample helper rejects bad input in two ways.
- It accepts only the application's canonical tenant ID format, so the ID cannot alter the key structure. Its example allows letters, numbers, underscore and hyphen up to 128 characters.
- It rejects object paths that are empty, absolute, contain a parent directory segment or use backslashes.
Do both. Never concatenate raw client input into a key.
Authorize before signing
For direct downloads, the cheat sheet says to authorize access to the exact object and operation before serving or generating a signed URL. It adds that signed URLs should be limited to the required object and method, with a lifetime suited to the operation and revocation model, and that the tenant identifier does not need to appear in the URL when authorization happened before signing.
Remember what a signed URL is. Anyone holding it can use it until it expires. So keep the lifetime short and never sign for a path the caller was not authorized to touch.
Watch for prefix collisions
The sample delete routine in the sheet includes a trailing delimiter in the prefix so a tenant named acme does not match another tenant's acme-west. The same logic applies to listing and policy conditions. Test with two tenants whose IDs share a starting string.
Encryption and versions
Tenant-specific encryption keys are an option when risk or compliance requires cryptographic isolation, though the sheet says a shared managed key with enforced access context can also be appropriate. On deletion, it notes current objects, versions and backups follow retention policy, so a delete helper that removes only current objects does not finish offboarding.
Checklist
- Classify objects as global, tenant-scoped or user-scoped.
- Keep intentionally shared assets in an explicit global namespace.
- Validate tenant ID format and object path.
- Authorize each get, put and signed URL request.
- Use short lifetimes and single-object, single-method signing.
- Store and check tenant metadata as defense in depth.
- Test with two tenants, including IDs with a shared prefix.
Try it yourself
Click through it at your own pace, or open it full screen. Look at how requests are varied against a running app, the style of probing that finds a file route trusting a client-supplied path.
Safeguard supports dependency scanning for the storage SDKs you use, and a free scan at gold.safeguard.sh/scan.
Quick check
Is a random object name enough?
It reduces guessing but is not authorization. If the name leaks, the access check must still stop the request.
Should I put the tenant ID in the signed URL?
You can, but you do not need to. What matters is that you authorized the request before signing.
Sources
Last reviewed: 19 October 2026.