Cross-tenant record access via /api/projects/:id
Severity
High
Confidence
High
- Evidence
- Using the approved org-a-member role, GET /api/projects/8121 returned a project record owned by Organization B (HTTP 200, full record). The handler verifies that the caller is authenticated but never checks that the project's organization matches the caller's membership.
- Business impact
- Any authenticated member of any organization can read other organizations' project records by enumerating sequential IDs. In the trigger context — an enterprise prospect's due-diligence questionnaire — this is exactly the class of failure the prospect is asking about.
- Remediation
- Add an organization-membership predicate to the server-side query (project belongs to one of the caller's organizations) and return 404 rather than 403 to avoid ID enumeration. Apply the same predicate to the related export endpoint.
- Scope and limitation
- Reproduced in the staging environment with approved test tenants and the recorded request budget. Tokens redacted.
Retest: Fixed and retested 2026-07-18 — cross-tenant requests now return 404.