Release evidence leaks public/confidential issues of restricted projects

HackerOne report #745571 by xanbanx on 2019-11-25, assigned to @cmaxim:

Hi GitLab Security Team,

Summary

GitLab recently added a feature called Release evidence (https://docs.gitlab.com/ee/user/project/releases/#release-evidence). The goal of this feature is to collect all created issues for one release (link happens via the assigned milestone). When a release is created, you then can download this snapshot of issue data via a new endpoint provided by the release API.

However, here comes the problem. This endpoint does not respect the users issue privileges. It only checks if the user has access to a release but not to the issue tracker of this project.

Thus, any unauthorized user who van view the release but does not have access to the issues can download the evidence data and thus gets access to all associated issues. This includes the public (but restricted) issues but also the confidential issues.

Steps to reproduce

  1. Create a public project and restrict issues and merge requests to project members only
  2. Inside that public project, create a milestone, i.e., named My-Milestone
  3. Create a public issue and set the milestone to the previously created milestone
  4. Create a confidential issue and set the milestone to the previously created milestone
  5. Create a git tag, i.e., named v1.0
  6. Create a new release via the API with the milestone attached by using the following API call:
curl -X POST -H "Private-Token: <Private-Token>" https://example.gitlab.com/api/v4/projects/<project-id>/releases?tag_name=<v1.0>\&description=Public-release\&milestones[]=My-Milestone  
  1. When querying the release via the API, a new field evidence_file_path with an URL to the evidence is returned. As an unauthenticated users, visit this link, which is in the form of https://example.gitlab.com///-/releases/v1.0/evidence.json. The v1.0 corresponds to the git tag

This returns JSON data in similar to this one:

{
    "release": {  
        "id": 1,  
        "name": "My release",  
        "project": {  
            "id": 1,  
            "name": "My project",  
            "created_at": "2019-11-24T17:10:12.993Z",  
            "description": null  
        },  
        "tag_name": "v1.0",  
        "created_at": "2019-11-24T17:10:17.512Z",  
        "milestones": [  
            {  
                "id": 1,  
                "iid": 1,  
                "state": "active",  
                "title": "My-Milestone",  
                "issues": [  
                    {  
                        "id": 3,  
                        "iid": 1,  
                        "state": "opened",  
                        "title": "My public issue",  
                        "due_date": null,  
                        "created_at": "2019-11-24T17:10:15.123Z",  
                        "description": "This is a public issue",  
                        "confidential": false  
                    },  
                    {  
                        "id": 4,  
                        "iid": 2,  
                        "state": "opened",  
                        "title": "Secret confidential issue, RCE",  
                        "due_date": null,  
                        "created_at": "2019-11-24T17:10:15.653Z",  
                        "description": "This is a secret issue discussing a critical RCE vulnerability",  
                        "confidential": true  
                    }  
                ],  
                "due_date": null,  
                "created_at": "2019-11-24T17:10:14.857Z",  
                "description": null  
            }  
        ],  
        "description": "Public-release"  
    }  
}

As you can see, this leaks the issue titles and the description of the public issue and even more critical the also the title of the confidential issue. (property confidential: true).

Furthermore, the JSON response also leaks:

  • the milestone

The described steps also work for private projects. Here, Guest users, who don't have access to confidential issues can get access to them via the release evidence download.

Impact

The evidence feature leaks public issues and confidential issues to unauthorized users without issue access. Furthermore, milestones are leaked. Since, confidential issues are leaked, this raises to a critical vulnerability since those issues describe the most sensitive content inside a project.

Examples

As an unauthorized user visit the following release page: https://gitlab.com/wter23/evidence-test
As you can see from the side bar, you don't have access to the issue tracker.

Now visit https://gitlab.com/wter23/evidence-test/-/releases/v1.0/evidence.json to retrieve the payload of the evidence.
The response leaks the public and confidential issues, the git tag, and the milestone.

What is the current bug behavior?

Anyone with access to the release page can download the evidence snapshot and thus gets access to (confidential) issues, milestone data, and the git tag, which is restricted.

What is the expected correct behavior?

If the user does not have access to the issues, the evidence snapshot cannot be downloaded.

Output of checks

This bug happens on GitLab.com running on version GitLab Enterprise Edition 12.5.0-pre e56cf44d (Canary)

Best regards,
Xanbanx

Impact

See above.