Verified: admin can leak root access token and escalate to Root
Summary
An authenticated admin can retrieve the root user's reusable management access_token from the admin-only user listing/search APIs and then use that token in the Authorization header to access Root-only endpoints. This creates a practical admin -> root privilege-escalation chain and results in full compromise of Root-only configuration APIs.
Details
The repository defines admin and root as distinct privilege levels:
RoleAdminUser = 10RoleRootUser = 100
The Root-only configuration API is explicitly protected with RootAuth():
GET /api/option/PUT /api/option/
However, the admin-only user batch APIs return user objects that still include the access_token field:
GET /api/user/GET /api/user/search
Relevant code paths:
model/user.goUser.AccessTokenis JSON-serializableGetAllUsers(...)omitspasswordbut notaccess_tokenSearchUsers(...)omitspasswordbut notaccess_token
router/api.go/api/user/and/api/user/searchare protected byAdminAuth()/api/option/is protected byRootAuth()
middleware/auth.goAuthorizationis accepted as a managementaccess_token- once valid, the caller inherits the target user's role and identity
This means an ordinary admin can:
- call the admin-only user list/search API
- read the
rootuser'saccess_tokenfrom the JSON response - replay that token in
Authorization - successfully cross the
RootAuth()boundary and invoke Root-only APIs
This appears unintended for two reasons:
- the codebase clearly separates
adminandroot - the single-user read path already contains stronger protection:
GetUser(...)blocks admins from reading same-level or higher-privilege usersGetUserById(..., false)omitsaccess_token
So the vulnerable behavior is specifically the batch/list/search path leaking a reusable higher-privilege credential.
PoC
Verified locally with Docker on a fresh instance.
Environment
- Image:
justsong/one-api:latest - Fresh database
- Default bootstrap root account present
Steps
Start a fresh instance.
Log in as the default root account:
- username:
root - password:
123456
- username:
Create a normal user, for example:
- username:
adm1n - password:
password123
- username:
Promote that user to
admin.Log in as
adm1n.Request the admin-only user list:
GET /api/user/
Cookie: <admin session cookie>- Observe that the response includes all listed users'
access_tokenvalues, including therootuser's token. Example response fragment:
{
"id": 1,
"username": "root",
"role": 100,
"access_token": "<root_access_token>"
}- Control check: try to access the Root-only options API using only the admin session:
GET /api/option/
Cookie: <admin session cookie>Observed result:
{"message":"无权进行此操作,权限不足","success":false}- Reuse the leaked root token:
GET /api/option/
Authorization: <root_access_token>Observed result:
- request succeeds
- Root-only configuration data is returned
This proves the leaked credential is directly reusable for privilege escalation.
Impact
This is an authenticated privilege-escalation vulnerability affecting any deployment where a user has admin access but should not have root access.
Impact includes:
admin -> rootprivilege escalation- unauthorized access to Root-only APIs
- exposure of sensitive global configuration
- potential unauthorized modification of system-wide settings
- compromise of the highest-privilege application account
Suggested CWE mapping:
CWE-200— Exposure of Sensitive Information to an Unauthorized ActorCWE-269— Improper Privilege Management
Source: songquanpeng/one-api