NVD has published CVE-2026-77776, a CVSS 9.1 (Critical), network-exploitable vulnerability in Headroom's LLM proxy — the intermediary component many organizations deploy (typically as a Docker container) between internal applications and LLM providers such as OpenAI-compatible APIs. The proxy maintains per-user memory: stored conversational context that persists across sessions and is injected into future requests.
The flaw is an identity-binding failure — effectively an IDOR against an AI memory store. The proxy derives the memory owner directly from the x-headroom-user-id HTTP request header. That header is read verbatim at multiple points in headroom/proxy/handlers/openai.py, including the chat completion and websocket code paths, and nothing binds the header value to the authenticated caller. Any client that can reach the proxy over the network can simply name another user's identifier and read or write that user's stored LLM memory.
For defenders, the risk is twofold and serious:
- Cross-tenant data exposure. LLM memory routinely accumulates sensitive material — conversation history, internal business context, PII, and occasionally credentials or tokens pasted into prompts. An attacker who claims a victim's user ID inherits all of it.
- Memory poisoning / indirect prompt injection. Because the attacker can also write to a victim's memory, they can plant malicious instructions that will be silently injected into the victim's future LLM sessions — a persistent, hard-to-see prompt-injection channel that survives session restarts.
A 9.1 with a NETWORK attack vector and no availability impact is consistent with what we see here: unauthenticated, low-complexity exploitation producing high confidentiality and high integrity impact. There is no user interaction requirement, and the exploit primitive is a single HTTP header. Treat this as an emergency change.
Technical Analysis
Affected Component
- Product: Headroom LLM proxy (
headroom), tracked under the docker ecosystem listing at NVD and most commonly deployed as a container behind an ingress or reverse proxy. - Vulnerable code:
headroom/proxy/handlers/openai.py— direct reads ofx-headroom-user-idin the chat completion handler and websocket handler. - Affected versions: All releases prior to the fix. The remediation introduces a single identity-resolution seam,
resolve_memory_identity, in a new/updated moduleheadroom/proxy/identity.py. If that function is absent from your installed copy, assume the build is vulnerable. - Fix behavior:
resolve_memory_identityhonors thex-headroom-user-idheader only for loopback or explicitly allowlisted callers; for everyone else, the memory identity is cryptographically bound to the proxy-token fingerprint (and the operative authenticated principal), so a client can no longer self-declare an arbitrary owner.
How the Vulnerability Works — Defender's View of the Attack Chain
This maps cleanly to CWE-639 (Authorization Bypass Through User-Controlled Key) with elements of CWE-290 (Authentication Bypass by Spoofing):
- Reconnaissance. Attacker identifies an internet- or intranet-reachable Headroom proxy endpoint (chat completions path such as
/v1/chat/completions, or the websocket upgrade path). In many deployments the proxy was intended to be internal-only but is exposed through a misconfigured ingress. - Identity spoofing. Attacker sends a request with
x-headroom-user-idset to a victim identifier. User IDs in these deployments are frequently predictable — email addresses, employee IDs, or sequential identifiers harvested from other sources. - Read access. The proxy loads the victim's stored memory and returns it (or blends it into responses the attacker can exfiltrate).
- Write access / poisoning. The attacker submits crafted content that the proxy persists into the victim's memory store. Subsequent victim sessions inherit the poisoned context — a stored indirect prompt-injection payload.
- Persistence via websocket path. Because the websocket handler trusts the same header, long-lived streaming sessions offer a stable channel for ongoing read/write abuse.
Exploitation requires no credentials beyond whatever perimeter access already exists, no race conditions, and no special tooling — curl with one extra header is sufficient. That is the entire exploit.
Exploitation Status
- CISA KEV: Not listed at the time of writing.
- Confirmed in-the-wild exploitation: None publicly confirmed as of publication.
- PoC maturity: No public PoC is required for this bug class — the exploitation cost is effectively zero. Assume scanning and opportunistic abuse will begin immediately now that the CVE is public, particularly against internet-exposed LLM gateways.
Detection & Response
Detection here lives primarily at the edge: WAF, load balancer, ingress controller, or reverse-proxy logs. The single most reliable telemetry prerequisite is header capture for requests destined to the proxy — enable logging of the x-headroom-user-id header (and source IP) on your ingress today if you have not already. Without it, cross-tenant spoofing is nearly invisible.
The highest-fidelity behavioral signal is one client claiming multiple identities: a single source IP presenting several distinct x-headroom-user-id values against memory-bearing endpoints is almost never legitimate.
Sigma
Adapt field names (c_ip, cs_headers, c_uri, cs_host) to your web/proxy log pipeline. Replace the allowlist prefixes with your trusted service subnets.
---
title: Headroom LLM Proxy Spoofed Identity Header from External Source (CVE-2026-77776)
id: 8f2c1a47-3b9e-4d52-a761-9c4e5f0a2b83
status: experimental
description: Detects HTTP requests carrying the x-headroom-user-id identity header from non-loopback, non-allowlisted clients. On unpatched Headroom LLM proxies this header is trusted verbatim, enabling cross-tenant LLM memory access (CVE-2026-77776). Requires header capture in WAF, load balancer, or ingress logs.
references:
- https://nvd.nist.gov/vuln/detail/CVE-2026-77776
author: Security Arsenal
date: 2026/06/15
tags:
- attack.initial_access
- attack.t1190
logsource:
category: webserver
detection:
selection_header:
cs_headers|contains: 'x-headroom-user-id'
filter_loopback:
c_ip:
- '127.0.0.1'
- '::1'
filter_allowlist:
c_ip|startswith:
- '10.10.'
condition: selection_header and not filter_loopback and not filter_allowlist
falsepositives:
- Internal services on non-allowlisted subnets that legitimately assert user identity (add them to filter_allowlist)
level: high
---
title: Headroom LLM Proxy Memory Endpoint Reached from Untrusted Network
id: 4d7e9b12-6a3f-48c5-b920-1e7d3f8a5c64
status: experimental
description: Detects inbound requests to Headroom LLM proxy chat completion and websocket memory paths originating outside expected service networks. Network reachability of these endpoints is a precondition for CVE-2026-77776 exploitation and indicates an exposed or misconfigured proxy deployment.
references:
- https://nvd.nist.gov/vuln/detail/CVE-2026-77776
author: Security Arsenal
date: 2026/06/15
tags:
- attack.initial_access
- attack.t1190
logsource:
category: proxy
detection:
selection_uri:
c_uri|contains:
- '/v1/chat/completions'
- '/v1/completions'
- '/ws'
selection_host:
cs_host|contains: 'headroom'
filter_allowlist:
c_ip|startswith:
- '10.'
- '172.16.'
condition: selection_uri and selection_host and not filter_allowlist
falsepositives:
- Partner or VPN traffic routed through unexpected address space
level: medium
KQL (Microsoft Sentinel / Defender)
Hunt 1 assumes your WAF/ingress forwards CEF syslog (CommonSecurityLog) with header capture; adjust the extraction regex to your logging format. Hunt 2 locates the vulnerable software on managed endpoints via Defender process telemetry.
// Hunt 1 - Cross-tenant probing: one client claiming multiple x-headroom-user-id identities
// A single source presenting >1 distinct identity is a high-fidelity CVE-2026-77776 signal.
CommonSecurityLog
| where TimeGenerated > ago(7d)
| where Message has 'x-headroom-user-id'
| extend ClaimedIdentity = extract(@"x-headroom-user-id[:\s=]+([A-Za-z0-9._-]+)", 1, Message)
| where isnotempty(ClaimedIdentity)
| extend SrcIP = coalesce(SourceIP, DeviceAddress)
| summarize DistinctIdentities = dcount(ClaimedIdentity),
ObservedIdentities = make_set(ClaimedIdentity, 25),
RequestCount = count(),
TargetPaths = make_set(RequestURL, 10)
by SrcIP, bin(TimeGenerated, 1h)
| where DistinctIdentities > 1
| sort by DistinctIdentities desc
// Hunt 2 - Locate Headroom proxy processes on managed endpoints (Defender for Endpoint)
DeviceProcessEvents
| where TimeGenerated > ago(7d)
| where ProcessCommandLine has_any ('headroom', 'openai.py')
| project TimeGenerated, DeviceName, ProcessCommandLine, AccountName, InitiatingProcessFileName
| sort by TimeGenerated desc
Velociraptor VQL
Use this hunt artifact across your Linux/Docker host fleet to find running Headroom proxy processes and — critically — determine whether their listening sockets are bound to all interfaces (0.0.0.0 / ::), which is what makes this bug remotely exploitable.
-- CVE-2026-77776: Identify Headroom LLM proxy processes and network-exposed listeners.
-- A LISTEN socket bound to 0.0.0.0 or :: means the vulnerable proxy is reachable off-host.
LET headroom_procs = SELECT Pid, Name, CommandLine, Exe, Username, CreateTime
FROM pslist()
WHERE CommandLine =~ '(?i)headroom|openai.py'
SELECT Pid, Name, CommandLine, Username, Laddr, Raddr, Status
FROM netstat()
WHERE Status =~ '(?i)listen'
AND Pid IN (SELECT Pid FROM headroom_procs)
AND Laddr.IP IN ('0.0.0.0', '::')
Any row returned by that artifact is an exposed, potentially vulnerable proxy — triage immediately.
Verification & Interim Hardening Script
Run this on proxy hosts and Docker hosts. It checks for the package, audits the installed source for the resolve_memory_identity fix, enumerates container deployments, and flags listeners bound to all interfaces.
#!/usr/bin/env bash
# CVE-2026-77776 - Headroom LLM proxy identity-spoofing verification & exposure audit
set -uo pipefail
echo '== CVE-2026-77776 verification =='
# 1) Locate the installed proxy package and version
echo '[*] Checking for headroom package...'
if command -v pip3 >/dev/null 2>&1 && pip3 show headroom >/dev/null 2>&1; then
echo "[+] headroom $(pip3 show headroom | awk '/^Version:/{print $2}') installed"
else
echo '[-] headroom not installed via pip3 (check virtualenvs and containers)'
fi
# 2) Audit installed source for the fix (resolve_memory_identity seam)
SITE=$(python3 -c 'import headroom, os; print(os.path.dirname(headroom.__file__))' 2>/dev/null || true)
if [ -n "$SITE" ]; then
if [ -f "$SITE/proxy/identity.py" ] && grep -q 'resolve_memory_identity' "$SITE/proxy/identity.py"; then
echo '[+] PASS: resolve_memory_identity seam present - patched build'
else
echo '[!] FAIL: resolve_memory_identity missing - VULNERABLE to CVE-2026-77776'
echo '[!] Direct header reads in openai.py:'
grep -n 'x-headroom-user-id' "$SITE/proxy/handlers/openai.py" 2>/dev/null | head -20
echo '[!] Upgrade immediately: pip3 install --upgrade headroom'
fi
fi
# 3) Check Docker deployments
if command -v docker >/dev/null 2>&1; then
echo '[*] Running headroom containers:'
docker ps --format '{{.ID}}\t{{.Image}}\t{{.Ports}}' | grep -i 'headroom' || echo ' none found'
echo '[*] If present: pull the fixed image and recreate (docker compose pull && docker compose up -d)'
fi
# 4) Exposure check - listeners bound to all interfaces (review for proxy ports)
echo '[*] Listeners on 0.0.0.0 / [::] - verify the proxy is NOT exposed here:'
ss -lnt 2>/dev/null | awk 'NR==1 || $4 ~ /0\.0\.0\.0:|\[::\]:/'
If you cannot patch immediately, strip the spoofable header at the edge for everyone except loopback and explicitly allowlisted callers — this neutralizes the exploit primitive without touching the proxy itself:
# Interim edge mitigation (nginx): only trusted callers may pass the identity header.
# nginx drops proxy_set_header directives whose value is an empty string.
cat > /etc/nginx/conf.d/headroom-cve-2026-77776-map.conf <<'EOF'
map $remote_addr $headroom_forward_user_id {
default "";
127.0.0.1 $http_x_headroom_user_id;
::1 $http_x_headroom_user_id;
# 10.20.0.5 $http_x_headroom_user_id; # add trusted internal orchestrators here
}
EOF
# Inside your EXISTING server {} block that fronts the proxy, add:
# location / {
# proxy_pass http://127.0.0.1:8080;
# proxy_set_header x-headroom-user-id $headroom_forward_user_id;
# }
nginx -t && systemctl reload nginx
Remediation
- Patch immediately. Upgrade the Headroom proxy to the release containing the
resolve_memory_identityfix inheadroom/proxy/identity.py. For pip installs:pip3 install --upgrade headroom. For containerized deployments: pull the updated image and recreate (docker compose pull && docker compose up -d). Verify with the script above — presence ofresolve_memory_identityis your patched-build indicator. Confirm the exact fixed version against the project's release notes and the NVD entry: https://nvd.nist.gov/vuln/detail/CVE-2026-77776. - Remove network exposure. The proxy was designed to sit behind authenticated services. Bind it to loopback or a dedicated service interface, and enforce an allowlist at the ingress/firewall so only known orchestrators and application tiers can reach it. Any
0.0.0.0listener surfaced by the VQL hunt or the audit script is a finding. - Apply the edge mitigation (header stripping, above) as defense-in-depth even after patching — trusting client-supplied identity headers anywhere in your stack is an anti-pattern worth killing permanently.
- Rotate proxy tokens. The fix binds memory identity to the proxy-token fingerprint. If tokens may have been exposed or shared, rotate them so prior sessions cannot be correlated, and so any spoofed associations keyed to old fingerprints are invalidated.
- Audit the memory store for compromise. Review stored LLM memory for entries your legitimate users did not create — cross-tenant reads leave theft damage, but writes leave poisoned context that will keep firing after you patch. Purge or restore anomalous memory entries from known-good backups.
- Enable header logging for
x-headroom-user-idon your ingress/WAF and onboard the Sigma rules and Sentinel hunts above. Run the multi-identity hunt retroactively over available log retention to determine whether probing predated your patch window. - KEV status: CVE-2026-77776 is not in CISA's Known Exploited Vulnerabilities catalog as of this writing, so no federal remediation deadline applies. Given the trivial exploitation cost, treat it with KEV-level urgency anyway: patch within 72 hours or isolate the service.
The broader lesson for teams deploying LLM infrastructure: these gateways are privilege-concentration points. They hold cross-user conversational state, they terminate authentication for downstream model providers, and they are increasingly internet-adjacent. Inventory them, patch them like perimeter devices, and log them like authentication systems — because functionally, that is what they are.
Related Resources
Security Arsenal Penetration Testing Services AlertMonitor Platform Book a SOC Assessment vulnerability-management Intel Hub
Is your security operations ready?
Get a free SOC assessment or see how AlertMonitor cuts through alert noise with automated triage.