CVE-2026-102895: Inside the GPUStack “Real-IP” Bypass and the Loopback-Trust Flaw - Safe Security

CVE-2026-102895: Inside the GPUStack “Real-IP” Bypass and the Loopback-Trust Flaw

Nov 12, 2026 9 minute read

Artificial-intelligence infrastructure has quietly become some of the most privileged compute in the enterprise. GPUStack — an open-source manager that pools GPUs and serves large-language-model endpoints across a cluster — sits exactly on that tier: it holds cloud credentials, brokers model traffic, and can schedule workloads onto every worker node it manages. CVE-2026-102895 turns the front door of that control plane into an open one.

The flaw is an authentication bypass. A single, attacker-supplied HTTP header — X-GPUStack-Real-IP: 127.0.0.1 — is enough to make an unauthenticated network request be treated as the built-in administrator. No password, no token, no stolen session. GPUStack’s own advisory describes it bluntly: “Either path yields full, unauthenticated administrative access over the network,” and reports the issue was observed exploited in the wild against a version 2.1.1 deployment.

The reframe that drives this piece: the vulnerability is not that GPUStack trusts the loopback address. Plenty of software grants local callers extra latitude. The vulnerability is that, in its default configuration, GPUStack lets the client decide whether it is the loopback — and then hands that client the keys.

Vulnerability At a Glance

CVE ID CVE-2026-102895
Component GPUStack (open-source GPU cluster / AI model-serving manager)
CWE CWE-287 (Improper Authentication); CWE-290 (Auth Bypass by Spoofing); CWE-346 (Origin Validation Error)
CVSS v3.1 9.8 Critical — CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H
CVSS v4.0 Not published by the CNA at time of writing
Prerequisites Network reachability to the server API with the standalone defaults: gateway mode resolves to embedded and force_auth_localhost is false
Impact Unauthenticated admin access → account/config disclosure, persistent admin API keys, workload control over managed workers
Affected versions GPUStack < 2.2.0
Fixed versions 2.2.0 (upgrade to 2.2.2+ to also cover CVE-2026-102894)
Exploitation status Vendor reports in-the-wild exploitation against a v2.1.1 deployment; added to CISA KEV per secondary reporting (verify against the CISA catalog)

What actually breaks

GPUStack authenticates every API request in one function, get_current_user() in gpustack/api/auth.py. If no valid credential is presented, versions before 2.2.0 fall back to a convenience rule: if the caller is on localhost, treat them as the administrator. That rule is only as safe as the server’s ability to know who “localhost” really is — and that is precisely what breaks.

The caller’s address is resolved by a helper, client_ip_getter(). When GPUStack runs with its embedded gateway — the default for a standalone server — that helper does not read the real TCP peer. It reads a request header:

def client_ip_getter(request):
if gateway_mode == embedded: # default for a standalone server
return request.headers.get("X-GPUStack-Real-IP", "") # attacker-controlled
else:
return request.client.host

# in get_current_user(), after all credential checks fail:
if user is None and client_ip_getter(request) == “127.0.0.1”:
if not server_config.force_auth_localhost: # default: False
user = await User.first_by_field(session, “is_admin”, True) # becomes admin

The header exists for a legitimate reason: behind the gateway, GPUStack needs the forwarded client address. But nothing authenticates that the header came from the gateway. Any client on the network can set it. Combined with a loopback-trust rule that is enabled by default (force_auth_localhost is false), the result is a pure spoofing bypass:

Unauthenticated request
+ header: X-GPUStack-Real-IP: 127.0.0.1
|
v
client_ip_getter() returns "127.0.0.1" (reads the header verbatim)
|
v
get_current_user(): no creds + "loopback" + force_auth_localhost=False
|
v
request is bound to the first is_admin user -> FULL ADMIN, no credentials

This is a textbook origin-validation error (CWE-346) layered on an authentication-by-spoofing primitive (CWE-290): a trust decision is made on an input the attacker controls.

Impact: From an Open Door to Cluster Control

The bypass is not a narrow information leak. Because it resolves to the built-in administrator, everything the admin API can do becomes reachable to an anonymous caller. The impact escalates cleanly across three tiers.

Unauthorized Administrative Read

At the lowest tier, the attacker simply is the admin for read purposes. The same request that returns 401 Unauthorized without the header returns the administrator’s own account — and the full user directory, cluster topology, and server configuration — with it. The contrast between the vulnerable and patched builds is the whole story: identical request, opposite outcome.

CVE-2026-102895 - Best CTEM platform, CTEM

Figure 1: On vulnerable 2.1.1 (top), an unauthenticated request carrying X-GPUStack-Real-IP: 127.0.0.1 is served as the admin account (“is_admin”:true); the same request with no header returns 401. On patched 2.2.0 (bottom), the identical forged-header request is rejected with 401.

Full Administrative Control and Persistence

The admin API is not read-only. With the same primitive, an attacker can enumerate every account, modify server and worker configuration, and — most durably — mint a new administrator API key. That key is a standard bearer credential: it continues to grant admin access on its own, with no forged header, so the takeover survives any later attempt to filter the header at the edge. A ten-second bypass becomes permanent tenancy.

forged-header request ---> POST /v2/api-keys ---> attacker-owned admin token
(works with no header, indefinitely)

Workload Control → Code Execution on Workers

At the top tier, administrative control of an AI control plane is control of its compute. GPUStack’s advisory notes that the exploitation seen in the wild went further than reading data: attackers used custom backends to run reverse shells. An administrator can register model backends and push workload definitions that execute on managed worker nodes, and can read the cloud credentials GPUStack stores to reach provider GPUs. The authentication bypass is the entry; the blast radius is every node and secret the cluster touches.

CVE-2026-102895 - Best CTEM platform, CTEM

Figure 2: The full chain against the vulnerable target — the forged header turns an unauthenticated request into the admin (401 → 200), the attacker enumerates accounts, mints a persistent admin API key, and confirms that stolen key grants admin on its own with no header.

Why This Matters Beyond the Application Process

A bypassed login on a web app is bad; a bypassed login on a scheduler is systemic. GPUStack’s job is to place work on other machines, so an attacker who becomes its admin inherits a scheduling primitive across the fleet — not just data in one process, but execution on many. The credentials GPUStack holds to reach cloud GPU providers extend that reach past the cluster boundary into the account that pays for it. And because the trigger is a single header on a normal request, there is no malformed payload or crash to trip a monitor — the exploit looks like ordinary, successful API traffic.

Attack Scenarios

Scenario 1: Attacker → Server (inbound)

The direct case. The attacker reaches a GPUStack API that is exposed to the network — directly, or through a proxy that does not strip the header — and sends an ordinary request with X-GPUStack-Real-IP: 127.0.0.1. They are admin from the first request, then mint a key for persistence.

Attacker --HTTP + X-GPUStack-Real-IP: 127.0.0.1--> GPUStack API --> admin session

Scenario 2: Reverse Proxy → Server (same-host trust)

The second documented path needs no header at all. When GPUStack sits behind a same-host reverse proxy, inbound requests arrive at the application with a real TCP peer of 127.0.0.1. If the deployment is in the non-embedded mode that reads the true peer, every proxied request already looks like loopback — so the loopback-trust rule hands admin to whoever can reach the proxy.

Internet --> reverse proxy (same host) --peer=127.0.0.1--> GPUStack --> admin

Impact Beyond a Single Deployment

The affected code is GPUStack’s own, so this is not a shared-library fan-out across many products. The reach is instead organizational: GPUStack is deployed wherever teams pool GPUs for internal model serving, and those deployments tend to hold cloud keys, proprietary models, and inference data. One exposed control plane is enough to compromise the AI workloads — and the cloud spend — of an entire team.

How Enterprises Should Respond

The fix is specific and the compensating controls are concrete. Lead with patching; close the data path; then hunt.

  1. Patch first. Upgrade to GPUStack 2.2.0 or later, which removes the loopback→admin auto-authentication entirely and only honors X-GPUStack-Real-IP behind a valid internal gateway token. Prefer 2.2.2+, which also fixes the separate SAML bypass CVE-2026-102894. Confirm the running version from the API (/version), not just the deployment manifest.
  2. Strip the spoofable header at the edge. Until every instance is patched, configure the ingress / reverse proxy to delete any client-supplied X-GPUStack-Real-IP before forwarding. This is the single highest-value compensating control — it cuts the exact data path the exploit rides.
  3. Turn on force_auth_localhost. Set force_auth_localhost=true so the loopback-trust shortcut is disabled even where it would otherwise fire. Treat this as defense-in-depth, not a substitute for patching.
  4. Take the control plane off untrusted networks. The CVSS vector is AV:N for a reason. Bind GPUStack to an internal interface, put it behind authenticated access (VPN / mTLS / SSO), and never expose the admin API to the internet.
  5. Rotate credentials and reduce post-exploitation privilege. Because the bypass can mint persistent admin API keys, audit and rotate all GPUStack API keys and any cloud credentials the cluster holds after patching. Run workers with least privilege and constrain what a registered backend may execute.
  6. Hunt for the bypass signature. It leaves fingerprints in normal logs: requests carrying X-GPUStack-Real-IP from non-gateway sources, /v2/users or /v2/api-keys calls with no prior authenticated login, unexpected new admin API keys or accounts, and backends registered out of band. Alert on each.

Closing: The client should never get to say who it is

GPUStack’s loopback shortcut was a convenience; the bug was letting the caller supply the address that convenience trusted. Patch to 2.2.x, strip the header at the edge, and rotate what the bypass could have minted — then treat your AI control plane like the privileged system it is. Safe Security’s CTEM validates whether a control plane like this is actually reachable and exploitable in your environment, not merely which version it reports.

See how SAFE transforms your CTEM Unified exposure visibility, AI-driven prioritization, and quantified risk in business terms. Built for enterprise scale.