Summary
AcceptInvitation, DeclineInvitation and LeaveProject in the ChaosCenter authentication server authorize the caller with their JWT uid but then apply the mutation to a member id taken from the request body. Any project member can change another member's invitation state, including flipping the project owner to Exited, which permanently locks the owner out of their own project.
Details
File: chaoscenter/authentication/api/handlers/rest/project_handler.go
Functions: AcceptInvitation, DeclineInvitation, LeaveProject
Each handler runs validations.RbacValidator(c.MustGet("uid"), member.ProjectID, ...) against the caller's uid from the JWT context, then passes member.UserID, bound straight from the request JSON, into service.UpdateInvite. The repository's UpdateInvite builds the update with an array filter of elem.user_id == userID and _id == projectID as the only other predicate, so the write lands on whichever member the caller names rather than on the caller.
validations.MutationRbacRules admits Owner, Viewer and Executor on all three routes, so any project member (or any holder of a pending invite, for accept/decline) can reach them.
By contrast the sibling handlers that are meant to act on another member, RemoveInvitation and UpdateMemberRole, are gated at Owner and explicitly reject a UserID equal to the caller. These three are the self-service side and only ever have one valid subject.
PoC
As any accepted Viewer of project P holding a valid bearer token:
POST /leave_project with body {"projectID":"P","userID":"<owner-uid>"} and no role key.
Response is 200 {"message":"successful"}. The owner's members[] entry in the project document becomes invitation: "Exited", after which the owner's calls to /get_project/P return 401 from RbacValidator. /accept_invitation and /decline_invitation behave the same way for anyone holding a pending invite to the project.
Impact
Broken object level authorization. Any project member can alter another member's invitation state; the highest-impact case is a non-owner permanently removing the project owner's access to their own project. Once exited, the owner no longer matches CreateMatchStage or the $elemMatch in RbacValidator and cannot recover access.
Remediation
Use the authenticated uid as the subject of the UpdateInvite call in all three self-service handlers, since they only ever have one valid subject. Proposed in #5600.
Summary
AcceptInvitation,DeclineInvitationandLeaveProjectin the ChaosCenter authentication server authorize the caller with their JWT uid but then apply the mutation to a member id taken from the request body. Any project member can change another member's invitation state, including flipping the project owner toExited, which permanently locks the owner out of their own project.Details
File:
chaoscenter/authentication/api/handlers/rest/project_handler.goFunctions:
AcceptInvitation,DeclineInvitation,LeaveProjectEach handler runs
validations.RbacValidator(c.MustGet("uid"), member.ProjectID, ...)against the caller's uid from the JWT context, then passesmember.UserID, bound straight from the request JSON, intoservice.UpdateInvite. The repository'sUpdateInvitebuilds the update with an array filter ofelem.user_id == userIDand_id == projectIDas the only other predicate, so the write lands on whichever member the caller names rather than on the caller.validations.MutationRbacRulesadmitsOwner,ViewerandExecutoron all three routes, so any project member (or any holder of a pending invite, for accept/decline) can reach them.By contrast the sibling handlers that are meant to act on another member,
RemoveInvitationandUpdateMemberRole, are gated atOwnerand explicitly reject aUserIDequal to the caller. These three are the self-service side and only ever have one valid subject.PoC
As any accepted
Viewerof projectPholding a valid bearer token:POST /leave_projectwith body{"projectID":"P","userID":"<owner-uid>"}and norolekey.Response is
200 {"message":"successful"}. The owner'smembers[]entry in the project document becomesinvitation: "Exited", after which the owner's calls to/get_project/Preturn401fromRbacValidator./accept_invitationand/decline_invitationbehave the same way for anyone holding a pending invite to the project.Impact
Broken object level authorization. Any project member can alter another member's invitation state; the highest-impact case is a non-owner permanently removing the project owner's access to their own project. Once exited, the owner no longer matches
CreateMatchStageor the$elemMatchinRbacValidatorand cannot recover access.Remediation
Use the authenticated uid as the subject of the
UpdateInvitecall in all three self-service handlers, since they only ever have one valid subject. Proposed in #5600.