CVE-2026-77775: Headroom: SSRF via client-set upstream base URL
HIGHHeadroom's LLM proxy lets any client dictate the upstream host it talks to via the x-headroom-base-url header, and the code only checks that the value parses as a URL with a hostname — it never blocks loopback, RFC 1918, or cloud metadata addresses. Because the component is a proxy, the response from whatever host the attacker names comes straight back to them, and the Authorization header riding along on the request is forwarded unchanged to that attacker-controlled destination, so this is both an internal-network SSRF and a credential-theft primitive in one request. There's no EPSS score, no known public exploit, and it isn't in CISA KEV yet, but the attack needs no authentication and no user interaction (CVSS 8.6, AV:N/AC:L/PR:N/UI:N), and the project's own reference docker-compose.yml binds 0.0.0.0 with published ports and no HEADROOM_PROXY_TOKEN set — the exact insecure default the server warns about at its own startup — so teams that deployed via the documented quickstart are plausibly exposed right now. Patch to the version that ships upstream_guard.py (present from v0.36.1), or in the interim set HEADROOM_PROXY_TOKEN, bind to 127.0.0.1 instead of 0.0.0.0, and add egress/network-policy rules blocking the proxy host from reaching 169.254.169.254 and RFC 1918 ranges; alert on any x-headroom-base-url value outside an explicit allowlist of approved upstreams.
What is the risk?
High confidence, low-effort exploit: the flaw requires only a crafted HTTP header, no auth, no user interaction, and no special tooling (CWE-918, CVSS 8.6). Exploitability is amplified by the shipped reference deployment (docker-compose with --host 0.0.0.0, published ports, and no proxy token by default), which the server itself warns is insecure at startup — meaning many real deployments likely inherited the vulnerable default rather than a hardened config. There's no evidence of active exploitation (not in CISA KEV, no EPSS score, no public PoC or Nuclei template), so this should be treated as a high-priority patch item rather than an active-incident item. Impact is severe where exploited: confidentiality is fully compromised (C:H) because the proxy discloses internal service responses and forwards live credentials (the Authorization header) to an attacker-chosen host, with no integrity or availability impact.
How does the attack unfold?
What systems are affected?
| Package | Ecosystem | Vulnerable Range | Patched |
|---|---|---|---|
| headroom-ai | — | — | No patch |
Do you use headroom-ai? You're affected.
How severe is it?
What is the attack surface?
What should I do?
1 step1) Upgrade Headroom to the version containing headroom/proxy/upstream_guard.py (confirmed present at v0.36.1) which validates upstream destinations. 2) If upgrading isn't immediate, set HEADROOM_PROXY_TOKEN so passthrough/proxy routes require authentication, and stop binding --host 0.0.0.0 in docker-compose.yml — bind to 127.0.0.1 or a private interface and remove published ports from public networks. 3) Add network-layer egress controls on the proxy host blocking outbound access to 169.254.169.254 (and equivalent GCP/Azure metadata IPs) and RFC 1918/loopback ranges unless explicitly required. 4) Implement an allowlist of approved upstream hosts for x-headroom-base-url rather than accepting arbitrary client-supplied values. 5) Detection: alert on proxy logs where x-headroom-base-url resolves to a private/link-local/metadata IP, and monitor for anomalous outbound connections from the proxy host to non-LLM-provider destinations.
What does CISA's SSVC say?
Source: CISA Vulnrichment (SSVC v2.0). Decision based on the CISA Coordinator decision tree.
How is it classified?
Which compliance frameworks are affected?
This CVE is relevant to:
Frequently Asked Questions
What is CVE-2026-77775?
Headroom's LLM proxy lets any client dictate the upstream host it talks to via the x-headroom-base-url header, and the code only checks that the value parses as a URL with a hostname — it never blocks loopback, RFC 1918, or cloud metadata addresses. Because the component is a proxy, the response from whatever host the attacker names comes straight back to them, and the Authorization header riding along on the request is forwarded unchanged to that attacker-controlled destination, so this is both an internal-network SSRF and a credential-theft primitive in one request. There's no EPSS score, no known public exploit, and it isn't in CISA KEV yet, but the attack needs no authentication and no user interaction (CVSS 8.6, AV:N/AC:L/PR:N/UI:N), and the project's own reference docker-compose.yml binds 0.0.0.0 with published ports and no HEADROOM_PROXY_TOKEN set — the exact insecure default the server warns about at its own startup — so teams that deployed via the documented quickstart are plausibly exposed right now. Patch to the version that ships upstream_guard.py (present from v0.36.1), or in the interim set HEADROOM_PROXY_TOKEN, bind to 127.0.0.1 instead of 0.0.0.0, and add egress/network-policy rules blocking the proxy host from reaching 169.254.169.254 and RFC 1918 ranges; alert on any x-headroom-base-url value outside an explicit allowlist of approved upstreams.
Is CVE-2026-77775 actively exploited?
No confirmed active exploitation of CVE-2026-77775 has been reported, but organizations should still patch proactively.
How to fix CVE-2026-77775?
1) Upgrade Headroom to the version containing headroom/proxy/upstream_guard.py (confirmed present at v0.36.1) which validates upstream destinations. 2) If upgrading isn't immediate, set HEADROOM_PROXY_TOKEN so passthrough/proxy routes require authentication, and stop binding --host 0.0.0.0 in docker-compose.yml — bind to 127.0.0.1 or a private interface and remove published ports from public networks. 3) Add network-layer egress controls on the proxy host blocking outbound access to 169.254.169.254 (and equivalent GCP/Azure metadata IPs) and RFC 1918/loopback ranges unless explicitly required. 4) Implement an allowlist of approved upstream hosts for x-headroom-base-url rather than accepting arbitrary client-supplied values. 5) Detection: alert on proxy logs where x-headroom-base-url resolves to a private/link-local/metadata IP, and monitor for anomalous outbound connections from the proxy host to non-LLM-provider destinations.
What systems are affected by CVE-2026-77775?
This vulnerability affects the following AI/ML architecture patterns: LLM gateways/proxies, model serving, agent frameworks, API gateways.
What is the CVSS score for CVE-2026-77775?
CVE-2026-77775 has a CVSS v3.1 base score of 8.6 (HIGH). The EPSS exploitation probability is 0.59%.
What is the AI security impact?
Affected AI Architectures
MITRE ATLAS Techniques
AML.T0049Exploit Public-Facing ApplicationAML.T0055Unsecured CredentialsCompliance Controls Affected
What are the technical details?
Original Advisory
Headroom's LLM proxy lets a client choose the upstream destination with the x-headroom-base-url request header. _resolve_openai_upstream_base in headroom/proxy/handlers/openai.py accepts the header value, requires only that it parse with an http or https scheme and a hostname, and returns it for use as the upstream base; _select_passthrough_base_url in headroom/providers/proxy_routes.py reads the same header for the passthrough routes. No check rejects loopback, link-local, or RFC 1918 destinations, and because the component is a proxy the upstream response is returned to the caller, so the request reaches internal services and cloud metadata addresses and their responses are disclosed. The Authorization header accompanying the request is forwarded unchanged to the caller-designated host. 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.
Exploitation Scenario
An attacker discovers a Headroom proxy instance exposed on the internet (a likely outcome given the insecure docker-compose default). They send a normal-looking chat completion request but set the header x-headroom-base-url: http://169.254.169.254/latest/meta-data/iam/security-credentials/<role-name>. The proxy's _resolve_openai_upstream_base function accepts this as a valid http URL with a hostname, forwards the request — including the Authorization header meant for the legitimate LLM provider — to the cloud metadata service, and returns the response (temporary IAM credentials) directly to the attacker. The attacker now has valid cloud credentials scoped to the host's role, which they can use for lateral movement, data exfiltration from cloud storage, or further compromise of the victim's cloud environment — all without ever needing valid Headroom credentials.
Weaknesses (CWE)
CWE-918 — Server-Side Request Forgery (SSRF): The web server receives a URL or similar request from an upstream component and retrieves the contents of this URL, but it does not sufficiently ensure that the request is being sent to the expected destination.
Source: MITRE CWE corpus.
CVSS Vector
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:N/A:NReferences
- github.com/headroomlabs-ai/headroomproduct
- github.com/headroomlabs-ai/headroom/blob/v0.29.0/headroom/proxy/handlers/openai.pytechnical-description
- github.com/headroomlabs-ai/headroom/blob/v0.36.1/headroom/proxy/upstream_guard.pytechnical-description
- github.com/headroomlabs-ai/headroom/pull/2207issue-tracking
- vulncheck.com/advisories/headroom-proxy-sends-upstream-requests-to-a-client-supplied-base-url-without-address-validationthird-party-advisory
Timeline
Related Vulnerabilities
CVE-2025-512010.0smolagents: sandbox escape enables unauthenticated RCE
Same attack type: Data LeakageCVE-2023-376510.0MLflow: path traversal allows arbitrary file read
Same attack type: Data LeakageCVE-2025-282810.0LangChain RequestsToolkit: SSRF exposes cloud metadata
Same attack type: Auth BypassCVE-2025-5376710.0Azure OpenAI: SSRF EoP, no auth required (CVSS 10)
Same attack type: Privacy ViolationCVE-2026-2185810.0n8n: Input Validation flaw enables exploitation
Same attack type: Auth Bypass