# Group search leaks private MRs, code, commits

GitLab group search returned private merge requests, code blobs and commits from projects with private repositories to unauthenticated users.

- Payout: hidden
- Severity: high
- Program: GitLab
- Found by: rpadovani
- Disclosed: 2019-12-14
- CVE: CVE-2019-5487
- Write-up quality: 7/10
- Original: https://hackerone.com/reports/692252
- Library page: https://bugbountylibrary.com/r/h1%3A692252
- Tags: area:web domain:web impact:data-leak impact:internal-access kind:bounty platform:hackerone sev:high tech:rest technique:recon vuln:access-control vuln:info-disclosure

**Target:** gitlab.com group search endpoint (/search?group_id=...&scope=merge_requests|blobs|commits)
**Root cause:** Group-level search scoped results by group membership/visibility but failed to enforce per-project repository visibility, so projects with private code inside a public group had their MRs, blobs and commits indexed and returned.
**Steps:**
1. Create a public group containing a public project whose repository/code is set private; push code and open MRs.
2. While logged out, open the group and use the top-right search bar with a term from the private code/MR.
3. Select scope 'Merge requests' or 'Code' — private MRs and README blobs are returned.
4. Use wildcard `*` with `scope=merge_requests&group_id=9970&project_id=2670515` to enumerate all private MRs of a project.
5. Repeat with `scope=commits` to leak commit messages, e.g. `search=Merge+branch+%27433-idor-fix%27+into+%27staging%27`.
**How found:** Researcher searched gitlab-org group search for terms from a HackerOne report they had published (customers.gitlab.com) and noticed their own private MR/code appeared in results while logged out.
**Exploitation:** Unauthenticated attacker browses any public group, issues crafted /search URLs with group_id and scope parameters, and harvests private MR titles, code snippets and commit messages; wildcard search plus project_id filter enumerates all private MRs of a project.
**Insight:** When a platform has layered visibility (group public, project repo private), test every search scope (blobs, merge_requests, commits, wiki) at the group level with group_id and wildcard `*` — the index often ignores the inner project's repo visibility.

