Proposed API for additional claims within CI_JOB_JWT

Everyone can contribute. Help move this issue forward while earning points, leveling up and collecting rewards.

  • Close this issue

Release notes

Adding API to control additional claims within CI_JOB_JWT

Problem to solve

Using the CI_JOB_JWT with external services is hampered by the inflexibility of the claims found within. While each CI_JOB_JWT contains useful claims, the inability to add claims make integration with external services difficult, if not impossible.

The JWT RFC7519 specifies a group of "Registered Claim Names". Despite suggesting "None of the claims...are intended to be mandatory to use or implement in all cases", some external services depend on the existence of these claims. For example, AWS requires the presence (and thus validation) of an "aud" claim to support AssumeRoleWithWebIdentity. Additionally, the current inflexible solution does not allow for adding any Public Claim Names or Private Claim Names to support external systems requiring any other claim.

Systems known to benefit from this proposal (due to their support/use of JWT tokens) include:

  • AWS
  • GCloud
  • Azure
  • Kubernetes

To facilitate individual job control of claims, the following proposal is offered as a solution to adding additional claims via an API, as an extension of the current job/stage spec.

Intended users

  • Cameron (Compliance Manager)
  • Devon (DevOps Engineer)
  • Sidney (Systems Administrator)
  • Sam (Security Analyst)
  • Alex (Security Operations Engineer)
  • Allison (Application Ops)
  • Priyanka (Platform Engineer)

User experience goal

The user should be able to specify any additional claim for a project like this:

MyJob:
  jwt_claims:
    - aud:
        sts.amazonaws.com
  script:
  - aws sts assume-role-with-web-identity --role-arn "${AWS_ROLE_ARN}" --role-session-name "${CI_JOB_ID}:${CI_ENVIRONMENT_SLUG}" --web-identity-token "${CI_JOB_JWT}"

Proposal

  1. Add an optional "jwt_claims" section for each job, giving users the ability to supply additional claims.
  2. Additional claims defined at group/subgroup/project level default to immutable (mutable:false).
  3. Additional claims defined at group/subgroup/project level are inherited by the job running within, and honor mutability rules (ie, if a claim at the group level is mutable:false, the claim cannot be modified at the subgroup/project level - this results in a failed job exeuction).
  4. Jobs MAY add claims not explicitly enumerated at group/subgroup/project level.
  5. Jobs MAY modify claims set at group/subgroup/project level ONLY if these claims are defined with mutable:true.
  6. Jobs MAY NOT modify claims set at group/subgroup/project level if these claims are defined with mutable:false. This will be enforced at the linter level, as well as failing jobs which attempt to violate the rule.
  7. Jobs MAY NOT modify built-in claims. These built-in claims are treated as mutable:false. This will be enforced at the linter level, as well as failing jobs which attempt violate the rule.

Further details

unknown

Permissions and Security

Adding this claim will have no impact on permissions/security of Gitlab itself.

However, control of claims should be considered carefully to prevent privilege escalation in external services. Specifically, additional claims found in "jwt_claims" section SHALL NOT overwrite the default claims currently supplied in each CI_JOB_JWT. For example, if the user supplies a "nbf" or "user_email" claim, these will be discarded. Their values within the CI_JOB_JWT will continue to be autogenerated and considered immutable (from the perspective of the user creating/running the job).

Documentation

Related to this ticket to support Terraform

Availability & Testing

unknown

What does success look like, and how can we measure that?

  • When no additional job claims are made, CI_JOB_JWT contains only built-in claims.
  • The entire job execution fails if any additional job claim is an attempt to modify an existing claim which has mutable:false set. This includes built-in claims.
  • The CI_JOB_JWT contains built-in claims, as well as any claims set for this job (in the .gitlab-ci.yml file), AND those inherited from the group/subgroup/project hierarchy the job runs in.

What is the type of buyer?

This should be built-in for every user to facilitate easy/safe integration with any services consuming JWT tokens.

Is this a cross-stage feature?

unknown

Links / references

  1. #216259 (closed)
  2. https://www.rfc-editor.org/rfc/rfc7519.html#section-4
Edited Aug 28, 2025 by 🤖 GitLab Bot 🤖
Assignee Loading
Time tracking Loading