GitLab CI/CD job token

When a pipeline job is about to run, GitLab generates a unique token and injects it as the CI_JOB_TOKEN predefined variable.

You can use a GitLab CI/CD job token to authenticate with specific API endpoints:

The token has the same permissions to access the API as the user that caused the job to run. A user can cause a job to run by pushing a commit, triggering a manual job, being the owner of a scheduled pipeline, and so on. Therefore, this user must be assigned to a role that has the required privileges.

The token is valid only while the pipeline job runs. After the job finishes, you can’t use the token anymore.

A job token can access a project’s resources without any configuration, but it might give extra permissions that aren’t necessary. There is a proposal to redesign the feature for more strategic control of the access permissions.

You can also use the job token to authenticate and clone a repository from a private project in a CI/CD job:

git clone https://gitlab-ci-token:${CI_JOB_TOKEN}@gitlab.example.com/<namespace>/<project>

GitLab CI/CD job token security

To make sure that this token doesn’t leak, GitLab:

  • Masks the job token in job logs.
  • Grants permissions to the job token only when the job is running.

To make sure that this token doesn’t leak, you should also configure your runners to be secure. Avoid:

  • Using Docker’s privileged mode if the machines are re-used.
  • Using the shell executor when jobs run on the same machine.

If you have an insecure GitLab Runner configuration, you increase the risk that someone tries to steal tokens from other jobs.

Limit GitLab CI/CD job token access

Version history

You can limit the access scope of a project’s CI/CD job token to increase the job token’s security. A job token might give extra permissions that aren’t necessary to access specific private resources. If a job token is leaked it could potentially be used to access data that is private to the job token’s user. By limiting the job token access scope, private data cannot be accessed unless projects are explicitly authorized.

Control the job token access scope with an allowlist of other projects authorized to be accessed by authenticating with the current project’s job token. By default the token scope only allows access to the same project where the token comes from. Other projects can be added and removed by maintainers with access to both projects.

This setting is enabled by default for all new projects, and disabled by default in projects created before GitLab 14.1. It is strongly recommended that project maintainers enable this setting at all times, and configure the allowlist for cross-project access if needed.

For example, when the setting is enabled, jobs in a pipeline in project A have a CI_JOB_TOKEN scope limited to project A. If the job needs to use the token to make an API request to a private project B, then B must be added to the allowlist for A. If project B is public or internal, it’s not required to be added to the allowlist. The job token scope is only for controlling access to private projects.

Configure the job token scope limit

  1. On the top bar, select Menu > Projects and find your project.
  2. On the left sidebar, select Settings > CI/CD.
  3. Expand Token Access.
  4. Toggle Limit CI_JOB_TOKEN access to enabled.
  5. Optional. Add existing projects to the token’s access scope. The user adding a project must have the maintainer role in both projects.

There is a proposal to improve the feature with more strategic control of the access permissions.

Trigger a multi-project pipeline by using a CI job token

CI_JOB_TOKEN for multi-project pipelines was moved from GitLab Premium to GitLab Free in 12.4.

You can use the CI_JOB_TOKEN to trigger multi-project pipelines from a CI/CD job. A pipeline triggered this way creates a dependent pipeline relation that is visible on the pipeline graph.

For example:

trigger_pipeline:
  stage: deploy
  script:
    - curl --request POST --form "token=$CI_JOB_TOKEN" --form ref=main "https://gitlab.example.com/api/v4/projects/9/trigger/pipeline"
  rules:
    - if: $CI_COMMIT_TAG

If you use the CI_PIPELINE_SOURCE predefined CI/CD variable in a pipeline triggered this way, the value is pipeline (not triggered).

Download an artifact from a different pipeline

CI_JOB_TOKEN for artifacts download with the API was introduced in GitLab 9.5.

You can use the CI_JOB_TOKEN to access artifacts from a job created by a previous pipeline. You must specify which job you want to retrieve the artifacts from:

build_submodule:
  stage: test
  script:
    - apt update && apt install -y unzip
    - curl --location --output artifacts.zip "https://gitlab.example.com/api/v4/projects/1/jobs/artifacts/main/download?job=test&job_token=$CI_JOB_TOKEN"
    - unzip artifacts.zip

Read more about the jobs artifacts API.

Troubleshooting

CI job token failures are usually shown as responses like 404 Not Found or similar:

  • Unauthorized Git clone:

    $ git clone https://gitlab-ci-token:$CI_JOB_TOKEN@gitlab.com/fabiopitino/test2.git
    
    Cloning into 'test2'...
    remote: The project you were looking for could not be found or you don't have permission to view it.
    fatal: repository 'https://gitlab-ci-token:[MASKED]@gitlab.com/<namespace>/<project>.git/' not found
    
  • Unauthorized package download:

    $ wget --header="JOB-TOKEN: $CI_JOB_TOKEN" ${CI_API_V4_URL}/projects/1234/packages/generic/my_package/0.0.1/file.txt
    
    --2021-09-23 11:00:13--  https://gitlab.com/api/v4/projects/1234/packages/generic/my_package/0.0.1/file.txt
    Resolving gitlab.com (gitlab.com)... 172.65.251.78, 2606:4700:90:0:f22e:fbec:5bed:a9b9
    Connecting to gitlab.com (gitlab.com)|172.65.251.78|:443... connected.
    HTTP request sent, awaiting response... 404 Not Found
    2021-09-23 11:00:13 ERROR 404: Not Found.
    
  • Unauthorized API request:

    $ curl --verbose --request POST --form "token=$CI_JOB_TOKEN" --form ref=master "https://gitlab.com/api/v4/projects/1234/trigger/pipeline"
    
    < HTTP/2 404
    < date: Thu, 23 Sep 2021 11:00:12 GMT
    {"message":"404 Not Found"}
    < content-type: application/json
    

While troubleshooting CI/CD job token authentication issues, be aware that:

  • When the CI/CD job token limit is enabled, and the job token is being used to access a different project:
  • The CI job token becomes invalid if the job is no longer running, has been erased, or if the project is in the process of being deleted.