Installing NPM package from different namespace with CI_JOB_TOKEN fails with 404
Summary
If you pull/install an NPM package from a public project with the CI_JOB_TOKEN
, then it will fail with 404
.
Without that token, it will succeed.
Steps to reproduce
user2
tries to download/install the @root/somepackage
, which is a public project.
# this line would suffice, since the project is public
@root:registry=https://<gitlab-url>/api/v4/packages/npm/
# but, by adding the following line, you'll a 404 error when you try to install
//<gitlab-url>/api/v4/packages/npm/:_authToken=${CI_JOB_TOKEN}
And then install in a job, i.e. npm install @root/somepackage
What is the expected correct behavior?
You should be able to pull it, especially since that works when you do not specify an authToken.
Root cause
Users can consume packages from the GitLab package registry in their CI pipelines. Packages belong to projects. It is common for users to authenticate using a CI_JOB_TOKEN when working in CI jobs.
Currently, if a user consumes/installs a package from a public project in a pipeline for a different project, the package is successfully installed because the request is anonymous, and the code will check Ability.allowed?(nil, :read_package, public_project)
and Ability.allowed?(nil, :read_project, public_project)
. Anonymous users have both :read_package
and :read_project
permissions for public projects, so both will return true
and the CI job will succeed.
However, if a job is authenticated using the CI_JOB_TOKEN, the code will check Ability.allowed?(ci_job_token, :build_read_project, public_project)
, which will return false
, and despite being a public project, the package installation will fail.
So why are we checking :build_read_project
instead of :read_project
(which will return true for the ci_job_token)?
In the find_project!
helper, when dealing with CI job token authentication, we try to limit the permissions of the job user. This happens here: https://gitlab.com/gitlab-org/gitlab/-/blob/572bb8c0fe055eb32030a8b48764113d8fe2aa6f/ee/lib/ee/api/helpers.rb#L93. You can see that when a user is present, we check :read_project
, but when a CI_JOB_TOKEN is present, we check :build_read_project
.
The Fix
Update the permissions to also allow :build_read_project
for public projects.