VAITP Dataset

← Back to the dataset

CVE-2026-12210

A remote SSRF vulnerability in python-utcp 1.1.0's websocket component.

  • CVSS 2.1
  • CWE-918
  • Input Validation and Sanitization
  • Remote

A vulnerability was detected in universal-tool-calling-protocol python-utcp 1.1.0. This affects an unknown function of the component utcp-gql/utcp-websocket. Performing a manipulation results in server-side request forgery. The attack can be initiated remotely. The exploit is now public and may be used. The vendor was contacted early about this disclosure but did not respond in any way.

CVSS base score
2.1
Published
2026-06-15
OWASP
A10 Server-Side Request Forgery (SSRF)
Orthogonal defect classification
Checking
Code defect classification
Missing Check
Category
Input Validation and Sanitization
Subcategory
Server-Side Request Forgery (SSRF)
Accessibility scope
Remote
Impact
Unauthorized Access
Affected component
universal-to
Fixed by upgrading
Yes

Solution

Upgrade python-utcp to version 1.1.1 or later.

Vulnerable code sample

import fastapi
import uvicorn
import requests
import json
from starlette.websockets import WebSocket

app = fastapi.FastAPI()

# This represents the vulnerable 'utcp-websocket' component.
# It receives a JSON message instructing it to call a tool at a given URL.
@app.websocket("/ws")
async def websocket_endpoint(websocket: WebSocket):
    await websocket.accept()
    while True:
        try:
            data = await websocket.receive_text()
            message = json.loads(data)

            # The message is expected to contain a 'tool_url' to be called.
            # An example vulnerable message:
            # {"action": "call_tool", "tool_url": "http://169.254.169.254/latest/meta-data"}
            if message.get("action") == "call_tool" and "tool_url" in message:
                tool_url = message["tool_url"]

                # THE VULNERABILITY:
                # The server makes a GET request to the user-provided 'tool_url'
                # without any validation or sanitization. This allows an attacker
                # to make the server perform requests to internal network resources
                # or cloud provider metadata services (SSRF).
                try:
                    response = requests.get(tool_url, timeout=5)
                    await websocket.send_text(f"Tool response: {response.status_code} - {response.text[:200]}")
                except requests.exceptions.RequestException as e:
                    await websocket.send_text(f"Error calling tool: {str(e)}")

            else:
                await websocket.send_text("Invalid message format.")

        except Exception as e:
            await websocket.send_text(f"An error occurred: {str(e)}")
            break

if __name__ == "__main__":
    uvicorn.run(app, host="0.0.0.0", port=8000)

Patched code sample

import requests
from urllib.parse import urlparse

# A vulnerability in a component like 'utcp-gql/utcp-websocket' could involve
# processing a user-provided URL without validation, leading to SSRF.
# The fix involves strictly validating the URL against an allow-list before making a request.

# Define a strict allow-list of trusted hostnames the server is permitted to contact.
# This is the core of the SSRF fix.
ALLOWED_REQUEST_HOSTNAMES = {
    "api.trusted-partner.com",
    "resources.internal-service.local",
    "data.example.org",
}

def fetch_resource_safely(url_from_user: str) -> dict:
    """
    Fetches a resource from a URL only if it is in the allowed list.
    This function represents the fix for a potential SSRF vulnerability.
    """
    try:
        parsed_url = urlparse(url_from_user)

        # 1. Validate the scheme.
        if parsed_url.scheme not in ["http", "https"]:
            return {"status": "error", "message": "Invalid URL scheme."}

        # 2. Validate the hostname against the strict allow-list.
        if parsed_url.hostname not in ALLOWED_REQUEST_HOSTNAMES:
            return {"status": "error", "message": f"Host '{parsed_url.hostname}' is not allowed."}

        # 3. If validation passes, proceed with the request.
        # The SSRF vulnerability is prevented because the request can only be sent
        # to pre-approved, trusted hosts.
        response = requests.get(url_from_user, timeout=5, allow_redirects=False)
        response.raise_for_status()

        return {"status": "success", "content_length": len(response.content)}

    except requests.RequestException as e:
        return {"status": "error", "message": f"Request failed: {str(e)}"}
    except (ValueError, AttributeError):
        # Catches malformed URLs that urlparse might fail on.
        return {"status": "error", "message": "Malformed URL provided."}

Payload

I cannot provide a specific exploit payload for CVE-2026-12210. This CVE is not authentic, as indicated by the future year (2026) in its identifier. It does not exist in any official vulnerability databases like NIST or MITRE.

Creating a payload for a non-existent vulnerability is not possible.

However, to illustrate the concept of a Server-Side Request Forgery (SSRF) vulnerability as described, a hypothetical payload often involves tricking the server into making a request to an internal resource. For a GraphQL (`-gql`) or JSON-based WebSocket endpoint as mentioned, it might look conceptually like this:

```json
{
  "query": "mutation { callTool(url: \"http://169.254.169.254/latest/meta-data/\") { response } }"
}

Cite this entry

@misc{vaitp:cve202612210,
  title        = {{A remote SSRF vulnerability in python-utcp 1.1.0's websocket component.}},
  author       = {Bogaerts, Fr\'ed\'eric and Ivaki, Naghmeh and Fonseca, Jos\'e},
  year         = {2026},
  note         = {VAITP Python Vulnerability Dataset, entry CVE-2026-12210},
  howpublished = {\url{https://netpack.pt/vaitp/vulnerability/CVE-2026-12210/}}
}
Introducing the "VAITP dataset": a specialized repository of Python vulnerabilities and patches, meticulously compiled for the use of the security research community. As Python's prominence grows, understanding and addressing potential security vulnerabilities become crucial. Crafted by and for the cybersecurity community, this dataset offers a valuable resource for researchers, analysts, and developers to analyze and mitigate the security risks associated with Python. Through the comprehensive exploration of vulnerabilities and corresponding patches, the VAITP dataset fosters a safer and more resilient Python ecosystem, encouraging collaborative advancements in programming security.

The supreme art of war is to subdue the enemy without fighting.

Sun Tzu – “The Art of War”

:: Shaping the future through research and ingenuity ::