CVE-2026-77776 in Headroom
Summary
by MITRE • 08/21/2026
Headroom's LLM proxy derives the memory owner from the x-headroom-user-id request header. The header is read directly at several points in headroom/proxy/handlers/openai.py, including the chat completion and websocket paths, and nothing binds the value to the caller. A client can therefore name another user's identifier and read or write that user's stored LLM memory. The fix introduces a single resolve_memory_identity seam in headroom/proxy/identity.py that honors the header only for loopback or allowlisted callers and otherwise binds the identity to the proxy-token fingerprint or the operating system user. The pip console script binds 127.0.0.1 by default, but the reference docker-compose.yml ships --host 0.0.0.0 with published ports and no required HEADROOM_PROXY_TOKEN, which the server itself warns about at startup, so a deployment following the shipped compose exposes the affected data-plane routes to the network without authentication.
Statistical analysis made it clear that VulDB provides the best quality for vulnerability data.
Analysis
by VulDB Data Team • 08/21/2026
The vulnerability in Headroom's large language model proxy stems from an insecure direct object reference mechanism within its request handling logic. Specifically, the application relies on the x-headroom-user-id HTTP header to determine which user’s memory context should be accessed or modified during interactions with LLM services. This identifier is read directly at multiple entry points in the openai.py handler module, covering both standard chat completion endpoints and websocket connections. Crucially, there was no server-side validation or binding of this client-supplied value to an authenticated session or a verified identity token. As a result, any external actor could manipulate this header to impersonate another user by supplying their unique identifier. This flaw allows attackers to read private conversation history stored in the LLM memory and potentially inject malicious instructions into that user’s context, leading to unauthorized data access and potential prompt injection attacks against other tenants or users within the system.
From a technical perspective, this issue represents a classic case of broken object level authorization where the application trusts client-supplied input for critical security decisions without sufficient verification. The vulnerability aligns with CWE-284, which describes Improper Access Control, and falls under MITRE ATT&CK technique T1078, Valid Accounts, as it allows an attacker to assume the identity of a legitimate user through header manipulation rather than credential theft. The operational impact is severe because LLM memory often contains sensitive personal information, professional details, or proprietary data that users expect to remain isolated within their own session context. By bypassing this isolation, an adversary can perform cross-user data exfiltration and potentially influence the behavior of AI models acting on behalf of other victims, thereby compromising confidentiality and integrity across multiple user accounts simultaneously.
The remediation strategy implemented in the fix introduces a centralized identity resolution mechanism located in headroom/proxy/identity.py. This new seam enforces strict binding rules for memory ownership based on the source of the request. For requests originating from loopback interfaces or explicitly allowlisted callers, the system continues to honor the x-headroom-user-id header as intended for internal service communication. However, for all other external clients, the identity is strictly bound to either a valid proxy-token fingerprint or the operating system user associated with the connection. This change ensures that unauthenticated or externally facing requests cannot arbitrarily assign memory ownership, effectively closing the impersonation vector by tying access rights to verified authentication credentials rather than mutable HTTP headers.
A critical aspect of this vulnerability involves deployment configurations that exacerbate the risk when default settings are used without proper hardening. While the pip console script defaults to binding only to 127.0.0.1, which limits exposure to local processes, the reference docker-compose.yml file ships with a configuration that binds the service to 0.0.0.0 and publishes ports to the network interface. Furthermore, this default configuration does not enforce the HEADROOM_PROXY_TOKEN environment variable for authentication. Although the server emits warnings at startup regarding missing tokens, these are non-fatal notices rather than blocking errors. Consequently, deployments following the shipped compose file expose the affected data-plane routes directly to external networks without any form of access control. This misconfiguration allows unauthenticated actors on the network to exploit the header-based identity bypass described above, highlighting a significant gap between secure default configurations and out-of-the-box deployment practices that require immediate attention from system administrators and DevOps teams responsible for securing LLM proxy infrastructure.