Skip to content

Leaked CI_JOB_TOKEN can be used for triggering pipelines in public projects despite scoping

Problem

Ci inbound job token scope which restricts whether a project can access your project only applies to private projects currently.

This makes sense for certain read permissions which are unrestricted for registered users on public projects. However, not all register users are allowed to write to projects or read secrets for a public project or trigger pipelines and therefore public projects also need to be prevented from taking certain actions if they are not allowed based on token scoping configurations.

The api endpoint to trigger pipelines, a write endpoint, can be accessed via the CI_JOB_TOKEN.

Example attack

User A (the malicious user) has developer access only to project A.

User B has owner access to project A and B.

The CI_JOB_TOKEN is leaked for user B and User A sees it.

User A can trigger a pipeline to deploy the application for public project B.

Detailed Steps: #405369 (comment 1382293144)

Proposal

The simplest thing to do is remove the exclusions for public and internal projects:

diff --git a/app/policies/project_policy.rb b/app/policies/project_policy.rb
index 68f126574476..889becc1fccf 100644
--- a/app/policies/project_policy.rb
+++ b/app/policies/project_policy.rb
@@ -655,7 +655,7 @@ class ProjectPolicy < BasePolicy
     enable :read_project_for_iids
   end

-  rule { ~public_project & ~internal_access & ~project_allowed_for_job_token }.prevent_all
+  rule { ~project_allowed_for_job_token }.prevent_all

   rule { can?(:public_access) }.policy do
     enable :read_package

This is the new proposal, as the previous one will break too much for the customers

we could align CI_JOB_TOKEN access with general access to the repo (Project->Settings->Visibility, project features, permissions). As in, the CI_JOB_TOKEN would respect project permissions settings. Details in #405369 (comment 1463412587)

Edited by Max Fan