Head pipeline leaked to unauthorized users via blocking merge request feature
Low
G
GitLab
Submitted None
Actions:
Reported by
xanbanx
Vulnerability Details
Technical details and impact analysis
### Summary
GitLab allows for public and internal projects to restrict the visibility of pipelines to project members only. Then, only project members should have access to the pipeline information.
GitLab recently added the blocking merge request feature. This feature can be used to leak the head pipeline thus bypassing the access control.
### Steps to reproduce
1. Create a public project, set Pipelines visibility to project members only, and disable public pipelines
2. Push some code and create a first merge request
3. Create a second merge request and add the first MR as a blocking MR
4. As a unauthenticated user visit the following page: `https://example.gitlab.com/<namespace>/<project-name>/merge_requests/2/widget.json`
This returns the JSON data for the merge request like the following example:
```json
{
"id": 34440035,
"iid": 2,
"description": "",
"title": "Add new file",
"approvals_before_merge": 0,
"blob_path": {
"head_path": "/wter23/test-blocking-mr-ci/blob/efe31a3611750142b47c5d9de374cd403d66c555",
"base_path": "/wter23/test-blocking-mr-ci/blob/1261949f29fd17e908f26a3e5461ff92ba6557ab"
},
"pipeline_id": 74726702,
"vulnerability_feedback_path": "/wter23/test-blocking-mr-ci/vulnerability_feedback",
"create_vulnerability_feedback_issue_path": null,
"create_vulnerability_feedback_merge_request_path": null,
"create_vulnerability_feedback_dismissal_path": null,
"rebase_commit_sha": null,
"rebase_in_progress": false,
"merge_pipelines_enabled": false,
"can_push_to_source_branch": false,
"has_approvals_available": true,
"rebase_path": null,
"approvals_path": "/wter23/test-blocking-mr-ci/merge_requests/2/approvals",
"api_approvals_path": "/api/v4/projects/13656291/merge_requests/2/approvals",
"api_approval_settings_path": "/api/v4/projects/13656291/merge_requests/2/approval_settings",
"api_approve_path": "/api/v4/projects/13656291/merge_requests/2/approve",
"api_unapprove_path": "/api/v4/projects/13656291/merge_requests/2/unapprove",
"blocking_merge_requests": {
"total_count": 1,
"hidden_count": 0,
"visible_merge_requests": {
"opened": [
{
"id": 34439968,
"iid": 1,
"title": "Add new file",
"state": "opened",
"reference": "!1",
"web_url": "/wter23/test-blocking-mr-ci/merge_requests/1",
"head_pipeline": {
"id": 74726535,
"sha": "e241af2ea6ee0e1292fa02c5e59c3ffc68311fa2",
"ref": "first",
"status": "success",
"web_url": "https://gitlab.com/wter23/test-blocking-mr-ci/pipelines/74726535",
"before_sha": "0000000000000000000000000000000000000000",
"tag": false,
"yaml_errors": null,
"user": {
"id": 4147327,
"name": "wter23",
"username": "wter23",
"state": "active",
"avatar_url": "https://secure.gravatar.com/avatar/a12221ea7cab0b84c088f1ab6e02724b?s=80&d=identicon",
"web_url": "https://gitlab.com/wter23"
},
"created_at": "2019-08-05T11:39:32.249Z",
"updated_at": "2019-08-05T11:44:16.900Z",
"started_at": "2019-08-05T11:39:33.294Z",
"finished_at": "2019-08-05T11:44:16.889Z",
"committed_at": null,
"duration": 277,
"coverage": null,
"detailed_status": {
"icon": "status_success",
"text": "passed",
"label": "passed",
"group": "success",
"tooltip": "passed",
"has_details": false,
"details_path": "/wter23/test-blocking-mr-ci/pipelines/74726535",
"illustration": null,
"favicon": "https://gitlab.com/assets/ci_favicons/favicon_status_success-8451333011eee8ce9f2ab25dc487fe24a8758c694827a582f17f42b0a90446a2.png"
}
},
"assignees": [],
"milestone": null,
"created_at": "2019-08-05T11:39:50.598Z",
"merged_at": null,
"closed_at": null
}
]
}
},
"state": "opened",
"in_progress_merge_commit_sha": null,
"merge_commit_sha": null,
"short_merge_commit_sha": null,
"merge_error": null,
"merge_params": {
"force_remove_source_branch": "0"
},
"merge_status": "can_be_merged",
"merge_user_id": null,
"auto_merge_enabled": false,
"auto_merge_strategy": null,
"available_auto_merge_strategies": [],
"source_branch": "second",
"source_branch_protected": false,
"source_project_id": 13656291,
"source_project_full_path": "wter23/test-blocking-mr-ci",
"squash": false,
"target_branch": "master",
"target_branch_sha": "1261949f29fd17e908f26a3e5461ff92ba6557ab",
"target_project_id": 13656291,
"target_project_full_path": "wter23/test-blocking-mr-ci",
"allow_collaboration": false,
"should_be_rebased": false,
"ff_only_enabled": false,
"metrics": null,
"merge_user": null,
"diff_head_sha": "efe31a3611750142b47c5d9de374cd403d66c555",
"default_squash_commit_message": "Add new file",
"default_merge_commit_message": "Merge branch 'second' into 'master'\n\nAdd new file\n\nSee merge request wter23/test-blocking-mr-ci!2",
"default_merge_commit_message_with_description": "Merge branch 'second' into 'master'\n\nAdd new file\n\nSee merge request wter23/test-blocking-mr-ci!2",
"commits_without_merge_commits": [
{
"message": "Add new file",
"short_id": "efe31a36",
"title": "Add new file"
}
],
"commits_count": 1,
"merge_ongoing": false,
"work_in_progress": false,
"source_branch_exists": true,
"mergeable_discussions_state": true,
"branch_missing": false,
"has_conflicts": false,
"can_be_merged": true,
"mergeable": false,
"remove_source_branch": false,
"project_archived": false,
"only_allow_merge_if_pipeline_succeeds": false,
"has_ci": true,
"ci_status": "success",
"source_branch_with_namespace_link": "<a href=\"/wter23/test-blocking-mr-ci/tree/second\">second</a>",
"source_branch_path": "/wter23/test-blocking-mr-ci/-/branches/second",
"current_user": {
"can_remove_source_branch": false,
"can_revert_on_current_merge_request": false,
"can_cherry_pick_on_current_merge_request": false,
"can_create_note": false,
"can_create_issue": false,
"can_update": false
},
"target_branch_commits_path": "/wter23/test-blocking-mr-ci/commits/master",
"target_branch_tree_path": "/wter23/test-blocking-mr-ci/tree/master",
"new_blob_path": null,
"conflict_resolution_path": null,
"remove_wip_path": null,
"cancel_auto_merge_path": null,
"create_issue_to_resolve_discussions_path": null,
"merge_path": null,
"cherry_pick_in_fork_path": null,
"revert_in_fork_path": null,
"email_patches_path": "/wter23/test-blocking-mr-ci/merge_requests/2.patch",
"plain_diff_path": "/wter23/test-blocking-mr-ci/merge_requests/2.diff",
"merge_request_basic_path": "/wter23/test-blocking-mr-ci/merge_requests/2.json?serializer=basic",
"merge_request_widget_path": "/wter23/test-blocking-mr-ci/merge_requests/2/widget.json",
"ci_environments_status_path": "/wter23/test-blocking-mr-ci/merge_requests/2/ci_environments_status",
"diverged_commits_count": 0,
"create_note_path": "/wter23/test-blocking-mr-ci/notes?target_id=34440035&target_type=merge_request",
"commit_change_content_path": "/wter23/test-blocking-mr-ci/merge_requests/2/commit_change_content",
"preview_note_path": "/wter23/test-blocking-mr-ci/preview_markdown?target_id=2&target_type=MergeRequest",
"merge_commit_path": null,
"test_reports_path": null,
"can_receive_suggestion": true,
"conflicts_docs_path": "/help/user/project/merge_requests/resolve_conflicts.md",
"merge_request_pipelines_docs_path": "/help/ci/merge_request_pipelines/index.md"
}
```
Notice, there is a `head_pipeline` pipeline field for the blocking MR, thus leaking the pipeline information although the unauthenticated user does not have access to the pipeline information.
### Impact
Pipeline information is leaked to unauthorized users.
### Examples
This happens on gitlab.com. You can visit https://gitlab.com/wter23/test-blocking-mr-ci/merge_requests/2/widget.json to see the information leak.
### What is the current *bug* behavior?
Head pipeline of blocking merge requests is leaked to users without access to the piplines.
### What is the expected *correct* behavior?
Users without access to the pipeline information cannot see the `head_pipeline` data.
### Relevant logs and/or screenshots
(Paste any relevant logs - please use code blocks (```) to format console output,
logs, and code as it's very hard to read otherwise.)
## Impact
See above
Report Details
Additional information and metadata
State
Closed
Substate
Resolved
Submitted
Weakness
Improper Access Control - Generic