CVE-2026-102895: GPUStack: Authentication bypass via trusted loopback source (reverse-proxy TCP peer or X-GPUStack-Real-IP header) grants unauthenticated admin
### Impact In GPUStack before v2.2.0, `get_current_user` (in `gpustack/api/auth.py`) promotes any request whose source is considered loopback to the built-in administrator account when `force_auth_localhost` is `False` (the default). The "source" is derived by `client_ip_getter`, which can be made to report `127.0.0.1` without any credentials in two ways: 1. **Same-host reverse proxy (TCP peer).** In the canonical self-hosted shape — GPUStack behind a same-host reverse proxy with `proxy_pass http://127.0.0.1:<port>` — every remote request arrives at GPUStack with TCP peer `127.0.0.1`, so the loopback auto-admin branch fires. No header or credential is required. Verified end-to-end against HEAD `6bee5883`. 2. **`X-GPUStack-Real-IP` header.** A forged `X-GPUStack-Real-IP: 127.0.0.1` header can cause the request source to be treated as loopback. Either path yields **full, unauthenticated administrative access** over the network: enumerate and modify users, models, workers, and configuration; mint persistent admin API keys (scope `["*"]`, valid from any source IP thereafter); read worker credentials and cloud/provider secrets. Combined with admin-only functionality such as `POST /v2/inference-backends/from yaml`, this leads to code execution on worker hosts. This vulnerability has been observed exploited in the wild against a v2.1.1 deployment (attacker-created custom backends running reverse shells). ### Root cause Trusting the network source of a request (socket peer, or a client-controllable header) as an authentication signal. When GPUStack is fronted by a same-host reverse proxy, the socket peer is always loopback, so the "localhost is trusted" assumption no longer holds. ### Patches Fixed in `gpustack` `2.2.0`: the loopback auto-admin path was removed and client-IP / forwarding-header handling was hardened. Upgrade to `2.2.0` or later. ### Workarounds - Set `force_auth_localhost=true` to require authentication even for loopback requests. - Ensure the reverse proxy / gateway cannot cause GPUStack to treat external traffic as loopback, and strip any client-supplied `X-GPUStack-Real-IP` header at the edge. - Keep the API off untrusted networks (VPN / edge authentication). ### Remediation (in the fix) Do not derive authentication from the request's network source. Remove implicit loopback-based admin, and only accept a real client-IP header from an authenticated/trusted gateway (never from arbitrary clients). ### Credit Independently reported by Nikko Enggaliano; Wei Yunzhou; and Rui Yang & Haoyu Wang (Johns Hopkins University). Active in the-wild exploitation was reported by Javier Sixto (ulex.fr).
Started
Nov 9, 2026, 10:15 PM UTC
Status
Ongoing
Elapsed
7h 32m
Verified sources