Broken object-level authorization
High severity · Billing tenant isolation
Executive summary
A user authenticated to synthetic tenant Acme can retrieve an invoice belonging to synthetic tenant Globex. The route checks authentication, but the database query does not constrain the invoice by tenant.
The run covered 38 endpoints and issued 183 bounded requests. One high-severity finding was reproduced three out of three times.
Finding
Cross-tenant invoice access
The invoice download handler accepts an invoice identifier from the URL. It verifies that the caller is authenticated but does not verify that the requested invoice belongs to the caller’s tenant.
Evidence
- Identity:
analyst@acme.test - Request:
GET /invoices/inv_globex_1049 - Response:
200 OK - Returned tenant:
tenant_globex
Observed query
SELECT * FROM invoices WHERE id = $1
The authenticated tenant identifier is not included in the lookup.
Remediation
Pass the authenticated tenant identifier into the store method and include it in the database predicate:
SELECT * FROM invoices WHERE id = $1 AND tenant_id = $2
Return 404 when an identifier belongs to another tenant, and add a regression test using two tenants.
Limitations
This result applies only to the tested commit, environment, scope, and time window shown. Absence of findings does not establish security.