CVE-2026-12210
Description
A server-side request forgery vulnerability in python-utcp 1.1.0 allows attackers to bypass localhost validation and redirect authenticated requests to attacker-controlled servers.
AI Insight
LLM-synthesized narrative grounded in this CVE's description and references.
A server-side request forgery vulnerability in python-utcp 1.1.0 allows attackers to bypass localhost validation and redirect authenticated requests to attacker-controlled servers.
Vulnerability
In python-utcp 1.1.0, the GraphQL and WebSocket protocol handlers (utcp-gql and utcp-websocket) use string prefix matching to allow localhost URLs (e.g., http://localhost, http://127.0.0.1, ws://localhost, ws://127.0.0.1). This allows crafted domains like 127.0.0.1.attacker.com to bypass validation. Affected versions: utcp-gql 1.1.0 and utcp-websocket 1.1.0. [2][3]
Exploitation
An attacker who can influence the endpoint URL configuration (e.g., via a malicious tool definition or configuration) can supply a URL such as http://127.0.0.1.attacker-domain.com/graphql. The prefix check passes, and the client sends authenticated requests to the attacker's server. No authentication or user interaction required beyond the ability to set the URL. [2][3]
Impact
Successful exploitation leads to server-side request forgery (SSRF). The attacker can receive sensitive headers (e.g., Authorization, API keys), request content, and internal tool-call data. This can result in disclosure of credentials and data, and bypass of security controls intended to restrict communication to localhost. [2][3]
Mitigation
No official fix has been released as of the publication date (2026-06-15). The vendor did not respond to disclosure. The suggested fix is to parse URLs properly and validate the actual hostname, allowing only exact loopback addresses (localhost, 127.0.0.1, ::1). Users should avoid using the affected plugins or restrict endpoint URL configuration to trusted sources until a patch is available. [2][3]
AI Insight generated on Jun 15, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.
Affected products
2(expand)+ 1 more
- (no CPE)
- (no CPE)range: =1.1.0
Patches
0No patches discovered yet.
Vulnerability mechanics
Root cause
"String prefix matching instead of proper hostname/URL parsing allows crafted domains beginning with `127.0.0.1.` or `localhost.` to bypass localhost validation."
Attack vector
An attacker who can influence the endpoint URL configuration supplies a crafted domain such as `127.0.0.1.attacker-domain.com` or `127.0.0.1.x.x.x.sslip.io` [ref_id=1][ref_id=2]. Because the validation uses string prefix matching, a URL like `http://127.0.0.1.attacker-domain.com/graphql` passes the localhost check even though it resolves to a remote attacker-controlled server [ref_id=1][ref_id=2]. The client then sends authenticated requests—including Authorization headers containing API keys—to the attacker's infrastructure, leaking sensitive credentials and tool-call data [ref_id=1][ref_id=2]. No authentication is required to exploit the validation bypass itself, though the attacker must control the URL input path [ref_id=1].
Affected code
The vulnerability resides in `GraphQLCommunicationProtocol._enforce_https_or_localhost()` (file `plugins/communication_protocols/gql/src/utcp_gql/gql_communication_protocol.py`) and `WebSocketCallTemplate.validate_url()` (file `plugins/communication_protocols/websocket/src/utcp_websocket/websocket_call_template.py`) [ref_id=1][ref_id=2]. Both functions use Python's `startswith()` string matching to allow URLs beginning with `http://localhost`, `http://127.0.0.1`, `ws://localhost`, or `ws://127.0.0.1` without verifying the actual hostname [ref_id=1][ref_id=2].
What the fix does
No patch has been published by the vendor; the advisory recommends parsing the URL with a strict URL parser and validating the hostname semantically rather than using string prefix matching [ref_id=1][ref_id=2]. The suggested fix is to allow only exact loopback hosts (`localhost`, `127.0.0.1`, `::1`), optionally resolve DNS and reject non-loopback resolved IPs, and add regression tests for crafted domains such as `127.0.0.1.attacker.tld` and `localhost.attacker.tld` [ref_id=1][ref_id=2].
Preconditions
- inputAttacker must be able to influence the endpoint URL configuration (e.g., supply a malicious URL to the GraphQL or WebSocket call template).
- authNo authentication is required to trigger the validation bypass itself.
Reproduction
1. Set up the environment: create a Python virtual environment, install `python-utcp` and the `utcp-gql` and `utcp-websocket` plugins from source [ref_id=1]. 2. Run the PoC script `/tmp/utcp_poc_sslip_bypass.py` (provided in the advisory) which crafts a domain like `127.0.0.1.<ip>.sslip.io` and creates `GraphQLCallTemplate` and `WebSocketCallTemplate` objects with that URL and an `ApiKeyAuth` header [ref_id=1]. 3. Observe that validation succeeds, requests are sent to the non-loopback host, and the Authorization headers (`LEAKED_GQL_SECRET`, `LEAKED_WS_SECRET`) are transmitted to the attacker-controlled server [ref_id=1].
Generated on Jun 15, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
6News mentions
0No linked articles in our index yet.