Why do individual project access tokens give access to all projects?

Hi everyone,

I’m using an on-prem GitLab 15.10.4, somewhat recently upgraded from 14.x and am not only storing source code in projects, but have lots of additional individual projects storing deployments of my product for customers as well. Those deployments contain mostly binary files like EXEs, DLLs, JARs and especially customized configs, templates etc. Some of the projects have special access tokens configured to give the customers themself read-only access to download their deployment using a web browser or some Git client and specially crafted URLs like in the following examples:

I needed to create additional access tokens right now, created a new Git-URL based on the copy of an existing one, replaced the password of the access token, but by accident forgot to change the name of the Git repo in the URL as well. Though, cloning the repo succeeded, while I would have expected it to fail, because the access token wasn’t configured for the repo in the URL. I’ve tested multiple other configurations and ANY created access token seems to provide read-only access to ALL repos in GitLab, regardless if they have access tokens configured at all. OTOH, if the token in the URL is wrong, e.g. because I changed the last character or added some random character or alike, the access to repos is forbidden as expected:

remote: HTTP Basic: Access denied. The provided password or token is incorrect or your account has 2FA enabled and you must use a personal access token instead of a password.

Is that behaviour by design?

I would have expected wrong access tokens for wrong projects result in denied access, like for overall wrong access tokens because if changed characters. Of course I don’t want customers to see all other projects only because they get one access token, which should be restricted to one project. I’m additionally somewhat sure I have tested this months before in the old GitLab when introducing this approach and things worked as expected. I mean, the name is “project access token”, the docs regularly mention phrases like project scope and stuff.

Might there be some mis-configuration, possibly because of the update?

I didn’t to that myself, maybe some system wide settings have been reset or whatever.

Or am I simply misunderstanding how those tokens work?

Thanks for your help!

I’ve additionally tested deploy tokens and when trying to clone some repo using some Git client I seem to have only access to the one repo the deploy token is configured for. Though, the web browser based archive creation doesn’t work for these kinds of tokens, because those URLs are considered part of the API. I have some customers not using Git clients (yet) and being able to download the repo using the browser is to benefit for those.

Additionally, I don’t understand why deploy tokens are restricted to their project during clones while project tokens are not. From my understanding both tokens should behave similar in that case, with project tokens simply being useful for more use-case if necessary, like accessing the API.

My GitLab uses private repos for individual users only and otherwise groups for different organisations containing repos all having the internal visibility instead of e.g. private. Reason is that multiple different users of different branches of the company should be able to browse all repos to see what’s there, possibly help with issues etc. Internal is documented the following in the web-UI:

Accessible by any user who is logged in.

Which is clearly the case once some project access token was used to authenticate at all. Though, the deploy token doesn’t seem to be covered by this and access is denied. Doesn’t make sense to me that a deploy and project access token are handled differently for the same operation of cloning some repo. Additionally, if project access tokens are considered in the above docs as well, they don’t make too much sense at all. That means one Internal project might be enough already to leak for any project access token despite its name and one can’t know when creating those tokens.

This is a pretty fundamental question, how can nobody know anything about it? Shouldn’t it be easy to answer how this feature is expected to work? :slight_smile:

There’s a recently opened issue, though I wonder why not a lot of more people recognized it yet.

Hey Thorsten,

Very interesting. TBH, I’d need to test it myself in order to see if this happens on my instance as well… Personally I never experienced it, but I also avoid using project access tokens, as they generally grant a lot - I prefer Deploy Tokens and restricting only what I need (read repo or read package registry, etc).

I guess it fell in one of those edge case scenarios that noone noticed so far. If it really is a bug, then (IMO) it is definitely a security issue.

I’m not sure myself is there a better way of reporting security issues other then opening an Issue (as it already is) - this forum is mostly Community only and every now and then some members from official GitLab Team. Perhaps we could have some help here from official stuff @dnsmichi or @sugaroverflow to know if there is a better way to communicate security flaws/issues?

In my opinion this might be not well documented but does behave as I would expect the project access token to behave:

  • Because a project access token is an "authenticated user, it is able to see/clone internal projects unless you specify that only specific projects should be allowed to clone.
  • For its own project you may define write permissions with specific levels of access (maintainer, developer, reporter, guest).
  • This is in line with how a group access token does behave.

Deploy tokens on the other hand are much more restricted and allow restrictions for very specific usecases.

Doesn’t make too much sense to me, deploy tokens only allow less permissions to be applied at all, like access to the API. Other than that, every aspect seems to be the same for those and project access tokens, like auto-generated usernames and stuff. Deploy tokens need to be authenticated users in the end as well. As can be read in the linked issue, I’m not the only one pretty surprised about the behaviour of project tokens.

At the very least, there would need to be a VERY big warning when creating project access tokens, that ANY project with internal visibility is readable by those. If group access tokens behave the same, in my opinion their are broken as well compared to the default behaviour of deploy tokens.

From the linked issue as well:

Even if we have revoked the ability to create project access tokens from all our groups, a user can create a personal repository, and create project access tokens that grants access to the rest of the projects.

Internal projects are seen by all users that are authenticated, and they can add themselves to the project and gain access pretty easily since they are effectively open projects. Private projects would require a user to request access.

I expect if your project was private instead of internal, then the access code/token given to it would only work for that given project, since it wouldn’t have access to any other “internal” ones which are almost like public projects (except that public don’t require authentication to see and use them like internal ones).

Alternatively, add your thoughts/issues/views to the issue that you linked so that Gitlab devs can take it under consideration and potentially fix that, or for them to explain why it’s like that. Assuming of course setting your projects to private is not an option for you to restrict access further than an internal project that doesn’t require a user/token to be a member to clone it or whatever.