Privilege escalation to Owner from a custom role with manage_group_access_tokens permission
## Problem On an instance with a custom role with base role of `Guest` with a custom permission of `manage_group_access_tokens` a low-privileged user can escalate themselves to `Owner` by being able to create an `Owner` level Group Access Token (GAT), from the UI and the [REST API](https://docs.gitlab.com/ee/api/group_access_tokens.html#create-a-group-access-token). Steps to reproduce the bug from the UI are mentioned below. For REST API, just make an API call to [this endpoint](https://docs.gitlab.com/ee/api/group_access_tokens.html#create-a-group-access-token) with a user who has a custom role `Guest` with a custom permission of `manage_group_access_tokens`. This is a [Medium](https://gitlab-com.gitlab.io/gl-security/appsec/cvss-calculator/?#vector=CVSS:3.1/AV:N/AC:L/PR:H/UI:N/S:U/C:H/I:H/A:N) severity ~"bug::vulnerability". ### Steps to reproduce 1. Create an instance level custom role on your self-managed instance with base role as `Guest` and adding `manage_group_access_tokens` permission. ![image](/uploads/54d5a8f3961e58e322bafcab61164314/image.png) 2. Assign this role to a member in a group using Rails console ``` group = Group.find_by_full_path('group-path') member = group.members.find_by(user_id: user-id) member.update(member_role: MemberRole.last) ``` 3. Custom role is assigned to the group member, `Eugene Thompson` ![image](/uploads/fd3e9679fefe604111388a3984a7b67c/image.png) 4. Login as `Eugene Thompson` and you will notice that you will be able to create GATs with `Owner` role ![image](/uploads/5bd36a8405c315ad940c732ba997dc86/image.png) 5. Verify that the Owner GAT has been created by making API calls with that GAT ![image](/uploads/c3374a5ea60afff06a270a7eaad368cf/image.png) `curl -H "PRIVATE-TOKEN: Guest GAT" https://gdk.test:3443/api/v4/groups/98/members/all | jq` ## Proposal Similar to https://gitlab.com/gitlab-org/gitlab/-/issues/433463#note_1729696309, a user with a custom role can only create a GAT with an access level that is less than or equal to their own access level, up to a maximum of `Maintainer`, if there custom role's base role is `Maintainer`. We must address this both in the UI and the REST API endpoints. I'm not sure if we have corresponding GraphQL endpoints that are affected by this issue as well? If so, we must address this bug there as well. /cc @jayswain @jrandazzo
issue