T05 · Unauthorized Access and Privilege Escalation
Error
- Location
- SKILL.md:64
- Finding
- Caller-Controlled Tenant Header Enables Tenant Impersonation<![CDATA[ ## Vulnerability Details **File Location**: `SKILL.md:64-66` **Vulnerability Type**: Unvalidated tenant identity selection **Risk Level**: High ### Vulnerable Code ```elixir tenant_id = get_req_header(conn, "x-tenant-id") |> List.first() assign(conn, :tenant_id, tenant_id) ``` ### Technical Analysis The documented tenant plug treats the caller-controlled `x-tenant-id` header as an authoritative tenant identity. It does not verify that: - The requester is authenticated. - The selected tenant exists. - The authenticated account is a member of the selected tenant. - The account has permission to perform the requested operation in that tenant. Authentication and tenant authorization are therefore disconnected. Any generated endpoint that relies on `conn.assigns.tenant_id` for isolation may operate on an arbitrary tenant selected by the requester. The header can be retained as a tenant selector only if its value is validated against trusted authentication claims or a server-side membership lookup. It must not itself grant tenant access. ### Attack Path 1. An attacker authenticates using a legitimate account. 2. The attacker learns or guesses the identifier of another tenant. 3. The attacker sends a request with `x-tenant-id` set to that tenant's identifier. 4. `SetTenant` assigns the attacker-supplied value to `conn.assigns.tenant_id` without membership validation. 5. Tenant-filtered context operations use the forged assignment and execute against the victim tenant. 6. Depending on the endpoint, the attacker can enumerate, create, or otherwise manipulate victim-tenant resources. ### Impact Assessment An authenticated user may cross tenant boundaries and exercise the API privileges associated with endpoints rather than the privileges granted by actual tenant membership. The potential scope includes unauthorized disclosure and manipulation of all resources selected through the forged tenant assignment. The precise data affected depends on which g ...[truncated 53 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions - Derive the active tenant from verified token claims when possible. - If `x-tenant-id` is used as a selector, verify it against a server-side membership and authorization record before assigning it. - Reject missing, malformed, unknown, or unauthorized tenant identifiers with an appropriate `401` or `403` response. - Store the validated tenant or membership record in `conn.assigns`, not merely the untrusted identifier. - Ensure create operations overwrite any client-provided `tenant_id` with the server-validated tenant identifier. - Add tests proving that an authenticated member of tenant A cannot list, create, read, update, or delete resources in tenant B. - Centralize tenant authorization in a plug or policy layer so individual controllers cannot accidentally omit it. ]]>
