Developer with Allowed to merge permission can bypass merging workflow to push an initial commit to the protected branch affecting its integrity

⚠️ Please read the process on how to fix security issues before starting to work on the issue. Vulnerabilities must be fixed in a security mirror.

HackerOne report #3149326 by theluci on 2025-05-15, assigned to @katwu:

Report | Attachments | How To Reproduce

Report

Hello, I hope you are doing well.
This report is similar to my other report #2708946.
However, this time using a very practical exploitation scenario which might be already being exploited.

Functionality

Gitlab provides a feature to set a few branches as protected in the top-level group.

Vulnerability

When creating a protected branch Gitlab doesn’t check if the Developer has Allowed to push permission or not, it only checks if the Developer has Allowed to merge permission.

<------------------------------------Important------------------------------------>

**This allows a Developer to bypass merging workflow to push an initial commit to the protected branch. (affecting it’s integrity) **

This can wreak havoc if the project has auto-deployments, which means malicious protected branch would be automatically pushed to a secure environment. For example, production.

<------------------------------------------------------------------------------------>

Steps to reproduce

  1. victim creates victim-group and activates ultimate trial.
  2. victim goes to victim-group, Manage -> Members and
  • Adds victim-member as Maintainer
  • Adds attacker as Developer
  1. victim goes to victim-group, Settings -> Repository, Expand Protected branches
  2. victim clicks on Add protected branch and adds protected branch production with the following configuration,

10may-1.png

It can be seen that only Maintainers have allowed to push permission. Thus, it is expected that only Maintainers could create production branch (which involves directly pushing an initial commit).

  1. victim creates a project victim-project inside victim-group.
    (Choose initialize repository with a README)

  2. victim adds file test.sh with the following content,

echo “safe code”  
  1. attacker creates a new branch branch from main.
  2. attacker changes test.sh in branch and creates a malicious commit as following,
echo “malicious code”  

attacker notes the SHA of the commit.

  1. attacker again changes test.sh in branch to a safe version and creates a safe commit as following,
echo “safe code”  
echo “some other safe code”  

This is done to smuggle one malicious commit in branch which would later be merged into main.

  1. attacker creates a merge request from branch to main.

In a real-world scenario, it might not be main but some development branch like dev which is fine as it is not the production branch.

  1. victim goes to victim-project, Code -> Merge requests and selects the merge request. (Created in step 10)

  2. victim switches to Changes tab and sees that only safe changes are being merged.

  3. victim merges the merge request.

  4. attacker goes to victim-project, creates a new branch production from main but intercept the request.

  5. In the body of the request, attacker changes &ref=main to &ref=<noted_SHA> (Noted in step 8)

  6. attacker forwards the request.

attacker has created a malicious production branch without having the Allowed to push permission.

In a real-world scenario, project might even have auto-deployments deploying malicious production branch to production server which can wreak havoc.

POC

Examples

This is my POC project (It is private so let me know if you need ownership),

What is the Current Bug behavior?

Developer can push and create a protected branch even though he is specifically not given Allowed to push permission and only given Allowed to merge permission. Thus, merging workflow should have been followed.

What is the Expected Correct behavior?

  • Developer with Allowed to merge permission should only be able to merge through the merging workflow.
  • Developer not given the Allowed to push permission should not be able to create the protected branch as it requires initial pushing.

Output of checks

This bug happens on GitLab.com (Probably on instance too).

Impact

  • Developer with Allowed to merge permission can bypass merging workflow to push an initial commit and create a protected branch. (Integrity: High)
  • This can wreak havoc if the project has auto-deployments, which means malicious protected branch would be automatically pushed to a secure environment. For example, production. (Scope: Changed, Integrity: High)

Attachments

Warning: Attachments received through HackerOne, please exercise caution!

How To Reproduce

Please add reproducibility information to this section: