Skip to content

fix(members): Scope invite-request role updates to caller's allowed roles#115807

Merged
oioki merged 2 commits into
masterfrom
fix/invite-request-role-validation
May 19, 2026
Merged

fix(members): Scope invite-request role updates to caller's allowed roles#115807
oioki merged 2 commits into
masterfrom
fix/invite-request-role-validation

Conversation

@oioki
Copy link
Copy Markdown
Member

@oioki oioki commented May 19, 2026

Align the PUT handler on OrganizationInviteRequestDetailsEndpoint with the approve path on the same endpoint and with the equivalent PUT on organization_member_details.

Previously, the role-update path constructed OrganizationMemberRequestSerializer with allowed_roles=roles.get_all(), so any caller who passed the member:write/member:admin scope check on the endpoint could set the invite's role to anything in the role table — including roles they themselves could not assign. The approve branch one block down already used get_allowed_org_roles(request, organization), so a Manager could not directly approve an owner invite, but they could rewrite a pending non-owner invite to owner and leave it for an Owner to approve from the request queue. The escalated role is persisted by the immediate member.save(), so the gap is observable in isolation as well as via the approve chain.

The fix is the one-line swap to get_allowed_org_roles(request, organization) in the update-path serializer context. The approve-side validate_invitation check is left as-is; it remains a correct second-stage gate on the approver's allowed roles.

Tests: test_manager_cannot_escalate_invite_role_to_owner and test_manager_cannot_escalate_invite_orgrole_to_owner exercise both the deprecated role and current orgRole shapes. They fail against master (200 + persisted owner role) and pass with the fix (400 + role unchanged).

Fixes CORE-167

…oles

The PUT handler on the invite-request details endpoint validated the
incoming role against roles.get_all() in the serializer context, while
the adjacent approve path correctly used get_allowed_org_roles(request,
organization). This left a Manager-level caller able to rewrite a
pending invite request to a role they were not authorized to assign
(e.g. owner); the escalated role would then be persisted by the
following save() and could be approved by any Owner reviewing the
queue.

Align the role-update path with the approve path and with the
equivalent PUT on organization_member_details. Add regression tests
covering both `role` and `orgRole` field shapes.

Co-Authored-By: Claude <noreply@anthropic.com>
@github-actions github-actions Bot added the Scope: Backend Automatically applied to PRs that change backend components label May 19, 2026
@oioki oioki marked this pull request as ready for review May 19, 2026 15:55
@oioki oioki requested a review from a team as a code owner May 19, 2026 15:55
@linear-code
Copy link
Copy Markdown

linear-code Bot commented May 19, 2026

CORE-167

…vite-request PUT

Without `creating_org_invite=True`, `get_allowed_org_roles` short-circuits
to an empty collection for any caller lacking the `member:admin` scope.
The endpoint's permission class accepts `member:write` or `member:admin`
for PUT, so a user auth token or org auth token scoped to `member:write`
only could previously update an invite request but would now receive a
400 on every role update — a regression introduced by the previous
commit.

Mirror the POST handler on OrganizationMemberIndexEndpoint: pass
`creating_org_invite=True`, and fall back to `[member]` for integration
tokens that have no associated OrganizationMember.

Add regression tests covering an internal integration token with
`member:write`: it can update an invite to the member role and is still
blocked from escalating to owner.

Co-Authored-By: Claude <noreply@anthropic.com>
@oioki oioki merged commit ecb4688 into master May 19, 2026
62 checks passed
@oioki oioki deleted the fix/invite-request-role-validation branch May 19, 2026 16:23
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Scope: Backend Automatically applied to PRs that change backend components

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants