VYPR
Unrated severityNVD Advisory· Published Jun 23, 2026

Capgo - Cross-Organization App Takeover via Mismatched org_id and app_id in /private/role_bindings

CVE-2026-56222

Description

Capgo before 12.128.2 contains an authorization bypass vulnerability in POST /private/role_bindings that fails to verify app_id ownership during app-scoped role binding creation. An attacker with administrative privileges in one organization can create role bindings targeting applications owned by other organizations, enabling unauthorized read and modification of victim applications.

AI Insight

LLM-synthesized narrative grounded in this CVE's description and references.

Affected products

1

Patches

Vulnerability mechanics

Root cause

"Missing ownership validation: `POST /private/role_bindings` authorizes the caller against the supplied `org_id` but does not verify that the target `app_id` belongs to that same organization."

Attack vector

An administrator of Org A sends a `POST /private/role_bindings` request with an `org_id` belonging to Org A and an `app_id` (the internal UUID) of an app owned by Org B. The endpoint checks only the caller's permission against `org_id` (Org A) and does not verify that the `app_id` belongs to the same organization. The binding is created under Org A's authorization context, but the RBAC engine later resolves the true owner of the app and grants the attacker's principal permissions over the Org B app. This enables the attacker to read and modify the victim app by controlling an API key or other principal that was bound with a privileged role [ref_id=1].

Affected code

The flaw resides in `supabase/functions/_backend/private/role_bindings.ts` where `POST /private/role_bindings` authorizes the caller against the user-supplied `org_id` but never verifies that the supplied `app_id` actually belongs to that organization [ref_id=1]. The `validateScope(...)` function only checks that `app_id` is present, not that it is owned by the authorized org. On the backend, `rbac_has_permission(...)` in `supabase/schemas/prod.sql` later resolves the real owner of the target app, making the binding effective against the actual owner org rather than the org used during authorization.

What the fix does

The advisory does not include a patch file, but the expected remediation is clear: the `POST /private/role_bindings` endpoint must verify that the `app_id` supplied in the request body belongs to the same organization as the `org_id` used for authorization. Without this ownership check, the binding created under one org's authorization context can grant effective privileges over a resource owned by a different org. The advisory explicitly states that the request should be rejected unless `app_id` belongs to the same organization [ref_id=1].

Preconditions

  • authThe attacker must be an administrator of at least one organization (Org A) with permission to call `POST /private/role_bindings`.
  • inputThe attacker must know the internal `apps.id` UUID of the victim application owned by another organization (Org B).

Reproduction

The advisory includes a full step-by-step proof of concept (Steps 1-6). An Org A administrator creates an API key with a known `rbac_id`, then sends a `POST /private/role_bindings` with `org_id` set to Org A and `app_id` set to the victim's internal app UUID. After the binding is created (200 OK), the attacker's API key gains `app_admin` access to the victim app, allowing both read and write operations [ref_id=1].

Generated on Jun 24, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.

References

2

News mentions

0

No linked articles in our index yet.