Summary
Capgo's bundle promotion API does not include the target channel when checking authorization, so channel-specific permission overrides may be skipped. A principal with app-level bundle-promotion permission could therefore promote a bundle to a channel that explicitly denies that operation, affecting channel version integrity.
Affected context
The issue occurs in the Capgo server backend's Supabase functions, specifically the PUT /bundle promotion path that dispatches to setChannel. It is relevant when a caller has an API key accepted by the endpoint and holds app-level channel.promote_bundle permission while the target channel has a restrictive per-channel override. The target channel is supplied by the request and is validated only after the authorization decision.
Exploit preconditions
- Attack surface: The PUT
/bundleAPI and its bundle-to-channel promotion flow - Required access: An API key with access to the endpoint and app-level
channel.promote_bundlepermission, such as permissions commonly associated with developer or uploader roles - Trigger point: A request that promotes a bundle using a supplied
channel_id - Why exploitation is possible: The authorization call provides the application identifier but omits the target channel identifier, causing channel-scoped override evaluation to receive a null scope and be skipped
Why this happens
The authorization check invokes checkPermission with the application scope but does not pass the request's target channel scope. The underlying RBAC routine evaluates channel-specific allow or deny overrides only when a channel identifier is non-null, so the missing context causes an explicit per-channel denial to be bypassed. This is an improper authorization design and maps to CWE-639: Authorization Bypass Through User-Controlled Key, because authorization is not consistently applied to the object or scope identified by the request.
Potential impact
- An authorized but insufficiently scoped principal may promote bundles to denied channels
- Public channel version metadata could be changed without the intended channel-level approval
- Release governance and deployment controls could be bypassed
- Consumers may receive an unintended or unauthorized bundle version
- Application integrity and auditability could be reduced
General mitigation guidance
Mitigation generally focuses on making authorization decisions complete, object-aware, and fail-closed.
Common defensive patterns include:
- Pass every security-relevant resource identifier, including the target channel, into authorization checks
- Evaluate per-channel deny and allow overrides before permitting state changes
- Treat missing authorization context as a denial rather than as an unrestricted scope
- Validate the target resource and its relationship to the application before performing authorization and mutation
- Separate permission evaluation from mutation and require the same fully resolved scope for both
- Apply least privilege to API-key roles and avoid granting broad promotion rights by default
How teams detect issues like this
Organizations can look for this class of issue through:
- Static analysis and code review checks for authorization calls that omit request-derived resource identifiers
- Review of RBAC functions for null-sensitive scope conditions and fail-open behavior
- Tests that combine app-level permissions with explicit per-resource deny overrides
- Policy checks requiring authorization before state-changing database updates
- Audit monitoring for bundle promotions by principals whose effective permissions lack the target channel scope
Automated security review tools may help identify authorization calls whose checked scope differs from the resource being modified.

