Removed author of the merge request can still edit merge request’s approval rules using API
:warning: **Please read **[**the process**](https://gitlab.com/gitlab-org/release/docs/-/blob/master/general/security/engineer.md)** on how to fix security issues before starting to work on the issue. Vulnerabilities must be fixed in a security mirror.** [**HackerOne report #2980839**](https://hackerone.com/reports/2980839) by `theluci` on 2025-02-07, assigned to `GitLab Team`: [Report](#report) | [Attachments](#attachments) | [How To Reproduce](#how-to-reproduce) ## Report Hello, I hope you are doing well. I found that the author of the merge request, removed from the project can still edit merge request’s approval rules using API even when the option isn’t available when using UI. #### Vulnerability According to [docs](https://docs.gitlab.com/ee/user/project/merge_requests/approvals/rules.html#edit-or-override-merge-request-approval-rules), to override the merge request’s approval rules, **You must have at least the _Developer role_ in the project.** ![1feb-5.png](https://h1.sec.gitlab.net/a/fd349966-a880-4524-8d92-0eb0545ed64b/1feb-5.png) If the author of the merge request is removed from the project and tries to edit approval rules of the merge request, he can not do so using UI ![1feb-6.png](https://h1.sec.gitlab.net/a/540bdf01-fd7b-4e91-83e8-a95aabe2829f/1feb-6.png) Which is correct and as per the documentation. **However, the check isn’t ensured when using API.**\ **That is, an author of the merge request, removed from the project can still override merge request’s approval rules using API contrary to documentation.** #### Steps to reproduce 1. `victim` creates a public group `victim-group` and starts Ultimate trial. 2. `victim` navigates to Manage --\> Members, + `victim` invites `victim-member` as a _Maintainer_ to `victim-group` + `victim` invites `attacker` as a _Developer_ to `victim-group` 3. `victim` creates a **public project** `victim-project` inside `victim-group`.\ _(Initialize repository with a README)_ 4. `victim` navigates to _Settings --\> Merge requests_, scrolls down to Merge request approvals, + `victim` sets the _Minimum required approvals_ to 2. + `victim` clicks _Add approval rule_ and selects the following configuration, ![6feb-1.png](https://h1.sec.gitlab.net/a/444fa10a-d7ce-4229-bf9b-cb856c0a909d/6feb-1.png) ![6feb-2.png](https://h1.sec.gitlab.net/a/3bbca083-9758-498b-967a-a48319647b30/6feb-2.png) + `victim` selects the following configuration, ![6feb-3.png](https://h1.sec.gitlab.net/a/7f5b1b5d-ca49-44cb-ab1e-7a98a2af3a32/6feb-3.png) **At this point, `victim` does not allow approval rules overriding and every merge request must be properly approved before being merged.** 5. `attacker` visits `victim-project`, creates a new branch `another` and makes some malicious changes. 6. `attacker` creates a merge request from `another` branch to `main`. 7. `victim` visits `victim-project`, navigates to _Code --\> Merge requests_ and selects the merge request. _(Created in step 6)_ 8. `victim` sets the merge request to **auto-merge**. `victim` hopes to merge the request after the required approval criteria has been met but not yet as to investigate/review the code further. 9. `attacker` visits `victim-project`, navigates to _Code --\> Merge requests_, selects the merge request _(Created in step 6)_ and marks it as **Draft**. 10. `victim` visits `victim-group`, navigates to Manage --\> Members and **Removes** `attacker`. 11. `victim` visits `victim-project`, navigates to _Settings --\> Merge requests_, scrolls down to Merge request approvals and **uncheck Prevent editing approval rules in merge requests**. ![6feb-4.png](https://h1.sec.gitlab.net/a/8a614ad6-f734-44a5-87ee-a6d1bcee1140/6feb-4.png) Now, `victim` allows approval rules overriding as only high role **trustworthy members** are in project and if required they can edit approval rules. \<------------------------------------Important-----------------------------------------------\> These members already have enough permissions to visit Settings and edit approval rules if required, so giving them permission to override approval rules isn’t a security concern.\ **Please note that while `attacker` was a part of the project approval rules overriding were not allowed.** In a real-world scenario, approval rules overriding would only be allowed in a very trusting environment, where members may already have enough permission to edit approval rules from Setting if required. Thus, for an `attacker`, not part of the project, to be able to edit a merge request’s approval rules is a grave security concern. \<-----------------------------------------------------------------------------------------------\> 12. `attacker` visits `https://gitlab.com/api/v4/projects/<victim-project-id>/approval_settings?target_branch=main` + `attacker` notes the `id` of `All Members` ![7feb-1.png](https://h1.sec.gitlab.net/a/e4b85585-5305-4a7b-8760-c5bf73b9d2ec/7feb-1.png) 13. `attacker` visits `victim-project`, navigates to _Code --\> Merge requests_ and selects the merge request. _(Created in step 6)_ 14. `attacker` clicks on _Edit_ and **unchecks Draft** ![6feb-5.png](https://h1.sec.gitlab.net/a/cf356531-389c-4fa9-a9f3-e4e12b73facb/6feb-5.png) 14. `attacker` clicks on _Save changes_ but **intercepts the request**. 15. `attacker` adds the following to the body of the request, ``` &merge_request%5Bapproval_rules_attributes%5D%5B%5D%5Bapproval_project_rule_id%5D=<ID_All_Members>&merge_request%5Bapproval_rules_attributes%5D%5B%5D%5Bapprovals_required%5D=0&merge_request%5Bapproval_rules_attributes%5D%5B%5D%5Bname%5D=&merge_request%5Bapproval_rules_attributes%5D%5B%5D%5Buser_ids%5D%5B%5D=&merge_request%5Bapproval_rules_attributes%5D%5B%5D%5Bgroup_ids%5D%5B%5D= ``` Please be sure to replace `ID_All_Members` with the ID noted in step 12. \<redacted\> 16. `attacker` forwards the request. `attacker` is able to **edit approval rules using API** despite not being a part of the project. 17. Merge request is merged. #### POC \<redactec\> #### Output of checks This bug happens on GitLab.com (Probably on instance too) #### Impact An author of the merge request, removed from the project can still override merge request’s approval rules **_using API (even though the option isn’t available when using UI)_ contrary to documentation**, which in worst-case scenario may merge malicious changes to the protected branch. ## Attachments **Warning:** Attachments received through HackerOne, please exercise caution! * [1feb-5.png](https://h1.sec.gitlab.net/a/fd349966-a880-4524-8d92-0eb0545ed64b/1feb-5.png) * [1feb-6.png](https://h1.sec.gitlab.net/a/540bdf01-fd7b-4e91-83e8-a95aabe2829f/1feb-6.png) * [6feb-1.png](https://h1.sec.gitlab.net/a/444fa10a-d7ce-4229-bf9b-cb856c0a909d/6feb-1.png) * [6feb-2.png](https://h1.sec.gitlab.net/a/3bbca083-9758-498b-967a-a48319647b30/6feb-2.png) * [6feb-3.png](https://h1.sec.gitlab.net/a/7f5b1b5d-ca49-44cb-ab1e-7a98a2af3a32/6feb-3.png) * [6feb-4.png](https://h1.sec.gitlab.net/a/8a614ad6-f734-44a5-87ee-a6d1bcee1140/6feb-4.png) * [6feb-5.png](https://h1.sec.gitlab.net/a/cf356531-389c-4fa9-a9f3-e4e12b73facb/6feb-5.png) * [7feb-1.png](https://h1.sec.gitlab.net/a/e4b85585-5305-4a7b-8760-c5bf73b9d2ec/7feb-1.png) * \<redacted\> * \<redacted\> ## How To Reproduce Please add [reproducibility information](https://about.gitlab.com/handbook/engineering/security/#reproducibility-on-security-issues) to this section: 1. 2. 3.
issue