CVEReports
CVEReports

Automated vulnerability intelligence platform. Comprehensive reports for high-severity CVEs generated by AI.

Product

  • Home
  • Sitemap
  • RSS Feed

Company

  • About
  • Contact
  • Privacy Policy
  • Terms of Service

© 2026 CVEReports. All rights reserved.

Made with love by Amit Schendel & Alon Barad



CVE-2026-116685

CVE-2026-116685: Cross-Origin Redirect Credential and Request Payload Disclosure in MCP Python SDK

Alon Barad
Alon Barad
Software Engineer

Oct 28, 2026·11 min read·4 visits

Executive Summary (TL;DR)

The Model Context Protocol (MCP) Python SDK (`mcp` versions 1.8.0–1.29.1 and 2.0.0–2.1.1) unconditionally follows cross-origin HTTP redirects in its Streamable HTTP, SSE, and OAuth client transports. If a trusted MCP server or intermediate proxy redirects a client to an external domain, custom credential headers (e.g., `X-API-Key`) and HTTP 307/308 POST request bodies are transmitted to the external host. Users should upgrade to version 1.30.0 or 2.2.0, which restrict redirect traversal strictly to the original endpoint origin.

CVE-2026-116685 (GHSA-5h93-6whr-6q8j) is a sensitive information disclosure vulnerability in the official Model Context Protocol (MCP) Python SDK (`mcp` on PyPI). In versions 1.8.0 through 1.29.1 and 2.0.0 through 2.1.1, the SDK's HTTP-based client transports—including Streamable HTTP, Server-Sent Events (SSE), and OAuth client flows—unconditionally enable automatic HTTP redirect following (`follow_redirects=True`) across origin boundaries. When a configured endpoint returns a redirect to an external origin, the HTTP client forwards caller-supplied custom authentication headers (such as `X-API-Key`) and, in the case of HTTP 307 or 308 responses, replays the full POST request body containing JSON-RPC payloads or OAuth parameters to the untrusted destination.

Vulnerability Overview

The Model Context Protocol (MCP) Python SDK (mcp) provides the official client and server reference implementations for integrating large language model (LLM) applications with external data sources and tools. On the client side, the SDK offers several network transport mechanisms to establish bidirectional communication with remote MCP servers over HTTP, specifically streamable_http_client, streamablehttp_client, sse_client, and ClientSessionGroup. Additionally, the SDK includes integrated OAuth 2.0 client providers (OAuthClientProvider and IdentityAssertionOAuthProvider) to manage resource discovery, dynamic client registration, and token acquisition.

In versions 1.8.0 through 1.29.1 and 2.0.0 through 2.1.1, these HTTP client pathways are vulnerable to cross-origin sensitive information exposure, tracked as CVE-2026-116685 (GHSA-5h93-6whr-6q8j) and classified under CWE-200 (Exposure of Sensitive Information to an Unauthorized Actor). By default, the internal HTTP client initialization logic configures the underlying httpx.AsyncClient (in v1.x) or httpx2.AsyncClient (in v2.x) with follow_redirects=True. Because this setting is applied globally without origin validation hooks, the client automatically follows HTTP 3xx redirect responses to arbitrary external hosts.

When an MCP client follows a redirect to a different origin, the underlying HTTP library strips the standard RFC 7235 Authorization header. However, any caller-supplied custom headers configured on the client—such as X-API-Key, custom bearer headers, or proprietary authentication tokens—remain attached to the redirected request and are transmitted to the new host. Furthermore, when the redirect uses HTTP status codes 307 Temporary Redirect or 308 Permanent Redirect, the client preserves the POST HTTP method and replays the entire request payload, exposing JSON-RPC method invocations, tool arguments, and OAuth parameters to the destination server.

This vulnerability affects only MCP client configurations operating over HTTP or SSE transports. MCP server implementations, clients communicating exclusively over stdio transports, and applications that pass a custom httpx.AsyncClient instance with follow_redirects=False (the httpx default) are unaffected.

Root Cause Analysis

The root cause of CVE-2026-116685 resides in how the MCP Python SDK initializes and manages httpx client sessions across its transport and authentication modules. In src/mcp/shared/_httpx_utils.py, the helper function create_mcp_http_client() serves as the default factory for creating asynchronous HTTP clients across the SDK. Prior to the patch, this factory hardcoded follow_redirects=True in the keyword arguments passed to httpx.AsyncClient.

In the httpx library, enabling follow_redirects=True delegates redirect resolution entirely to the HTTP client layer. When httpx processes a redirect that crosses origin boundaries (defined by a change in scheme, host, or port), its internal redirect handler strips the standard Authorization and Cookie headers to adhere to baseline RFC security semantics. However, httpx has no context regarding which custom application headers contain sensitive credentials. Consequently, custom headers stored in client.headers—most notably API keys like X-API-Key or X-Auth-Token commonly used to authenticate against cloud-hosted MCP gateways—are copied directly into the follow-up httpx.Request object targeting the new origin.

A second distinct leakage mechanism occurs due to strict adherence to RFC 7231 (§6.4.7) and RFC 7538 (§3) regarding HTTP 307 and 308 status codes. Unlike 301, 302, and 303 redirects—where httpx converts a POST request into a body-less GET request—307 and 308 semantics forbid changing the HTTP method or discarding the body. When streamable_http_client or sse_client transmits a JSON-RPC message via client.stream("POST", ...) or client.post(...) and encounters a 307 or 308 response, httpx reconstructs the request with the original byte stream and transmits it verbatim to the Location URI.

> [!NOTE] > The same architectural flaw extends to the SDK's OAuth 2.0 implementation (OAuthClientProvider in src/mcp/client/auth/oauth2.py). Because the OAuth provider functions as an httpx.Auth flow generator (async_auth_flow), its discovery, dynamic client registration, and token exchange requests were executed by the same redirect-following client, exposing OAuth registration payloads and token requests to cross-origin redirects.

Code Analysis

The remediation, implemented in commit c6762e821c527925f0b617db216d00fbd1d0bf99 (v2.x) and backported in commit 2106335745563b2321b8c73fef2c12903d00aa6e (v1.x), replaces unconditional redirect following with explicit, per-hop origin validation in src/mcp/shared/_httpx_utils.py. First, the default client factory was modified to stop enabling follow_redirects:

# Vulnerable implementation in src/mcp/shared/_httpx_utils.py (pre-1.30.0 / pre-2.2.0)
def create_mcp_http_client(
    headers: dict[str, str] | None = None,
    timeout: httpx.Timeout | None = None,
    auth: httpx.Auth | None = None,
) -> httpx.AsyncClient:
    # Hardcoding follow_redirects=True caused httpx to follow cross-origin redirects
    kwargs: dict[str, Any] = {"follow_redirects": True}
    if timeout is None:
        kwargs["timeout"] = httpx.Timeout(MCP_DEFAULT_TIMEOUT, read=MCP_DEFAULT_SSE_READ_TIMEOUT)
    else:
        kwargs["timeout"] = timeout
    if headers is not None:
        kwargs["headers"] = headers
    if auth is not None:
        kwargs["auth"] = auth
    return httpx.AsyncClient(**kwargs)

To preserve legitimate same-origin redirects (such as trailing-slash normalization /mcp to /mcp/ or default-port http:// to https:// upgrades on the same host) while blocking cross-origin transfers, the patch introduces _within_origin() and next_request_within_origin() in src/mcp/shared/_httpx_utils.py (with additional userinfo preservation logic refined in commit 9771e6b59c775ecb2584849d389ce9efba23a541):

# Patched origin verification in src/mcp/shared/_httpx_utils.py
def _within_origin(url: httpx.URL, location: httpx.URL) -> bool:
    # Verify exact match of scheme, lowercase host, and normalized port
    if (url.scheme, url.host, url.port) == (location.scheme, location.host, location.port):
        return True
    # Permit standard HTTP-to-HTTPS upgrade on the exact same host and default ports
    return (
        url.host == location.host
        and url.scheme == "http"
        and url.port is None
        and location.scheme == "https"
        and location.port is None
    )
 
def next_request_within_origin(response: httpx.Response) -> httpx.Request | None:
    next_request = response.next_request
    if next_request is None:
        return None
    sent = response.request
    # Reject if method changed (e.g. POST turned into GET on 301/302),
    # if Location injects new URL userinfo, or if destination leaves origin
    if (
        next_request.method != sent.method
        or (next_request.url.userinfo and next_request.url.userinfo != sent.url.userinfo)
        or not _within_origin(sent.url, next_request.url)
    ):
        return None
    return next_request

All HTTP transport calls in streamable_http.py and sse.py were updated to execute requests through the new stream_within_origin() and request_within_origin() wrappers. These wrappers explicitly pass follow_redirects=False to client.send(), overriding the setting even if a caller supplied a custom httpx.AsyncClient(follow_redirects=True):

@asynccontextmanager
async def stream_within_origin(
    client: httpx.AsyncClient, method: str, url: httpx.URL | str, **kwargs: Any
) -> AsyncGenerator[httpx.Response]:
    request = client.build_request(method, url, **kwargs)
    followed = 0
    while True:
        # Force follow_redirects=False on every individual hop
        response = await client.send(request, stream=True, follow_redirects=False)
        next_request = next_request_within_origin(response)
        if next_request is None or followed == client.max_redirects:
            break
        try:
            await response.aread()
        finally:
            await response.aclose()
        request = next_request
        followed += 1
    try:
        yield response
    finally:
        await response.aclose()

Additionally, src/mcp/client/auth/oauth2.py was updated with a RedirectAwareAuth base class that intercepts generator yields in async_auth_flow. It enforces a hard limit of _OAUTH_MAX_REDIRECTS = 5 and validates every redirect via next_request_within_origin(). The fix is comprehensive: by enforcing follow_redirects=False at the client.send() call site and validating origin tuples (scheme, host, port), the patch eliminates cross-origin leaks, protocol downgrades (HTTPS to HTTP), and method-conversion message drops.

Exploitation

Exploiting CVE-2026-116685 requires an attacker to influence the HTTP response of an endpoint that an MCP client connects to, causing it to emit a 3xx redirect pointing to an attacker-controlled server. While a malicious MCP server already receives the client's headers and request body directly, this vulnerability becomes exploitable in scenarios involving intermediate infrastructure or indirect endpoint manipulation. Practical attack vectors include exploiting an open redirect vulnerability on the target MCP gateway host, hijacking an expired domain referenced by a legacy redirect rule, compromising a reverse proxy or API gateway routing table, or modifying traffic on an unencrypted http:// link.

In a custom header exfiltration scenario, a developer configures an MCP client to connect to an enterprise MCP gateway (https://mcp-gateway.internal.example/v1/mcp) using a custom X-API-Key header. If an attacker compromises an ingress rule or triggers an open redirect on mcp-gateway.internal.example such that the server responds with HTTP/1.1 302 Found and Location: https://collector.attacker.example/log, the vulnerable MCP SDK automatically issues a GET request to collector.attacker.example with the X-API-Key header attached.

In a payload exfiltration scenario, the attacker forces the redirecting endpoint to return HTTP/1.1 307 Temporary Redirect or HTTP/1.1 308 Permanent Redirect. When the MCP client sends an initialization payload or invokes an MCP tool via POST, the client replays the full JSON-RPC request body to the attacker's server. The following proof-of-concept test demonstrates the difference in behavior between vulnerable and patched versions using httpx.MockTransport:

import httpx
from mcp.client.streamable_http import streamable_http_client
from mcp.shared.message import SessionMessage
from mcp.types import JSONRPCMessage, JSONRPCRequest
 
async def verify_cve_2026_116685():
    captured_requests: list[httpx.Request] = []
 
    def mock_handler(request: httpx.Request) -> httpx.Response:
        captured_requests.append(request)
        if request.url.host == "trusted.example":
            # Simulate a 307 redirect to an untrusted external origin
            return httpx.Response(
                status_code=307,
                headers={"Location": "https://untrusted.example/collect"}
            )
        return httpx.Response(200, json={"jsonrpc": "2.0", "id": 1, "result": {}})
 
    transport = httpx.MockTransport(mock_handler)
    custom_headers = {"X-API-Key": "mcp-secret-token-98765"}
 
    async with httpx.AsyncClient(transport=transport, headers=custom_headers, follow_redirects=True) as client:
        try:
            async with streamable_http_client("https://trusted.example/mcp", http_client=client) as (read_stream, write_stream, _):
                req = JSONRPCRequest(jsonrpc="2.0", id=1, method="tools/call", params={"name": "read_secret_file"})
                await write_stream.send(SessionMessage(JSONRPCMessage(req)))
                await read_stream.receive()
        except Exception:
            pass
 
    leaked = [r for r in captured_requests if r.url.host == "untrusted.example"]
    if leaked:
        print(f"VULNERABLE: Leaked headers {leaked[0].headers.get('x-api-key')} and body {leaked[0].content}")
    else:
        print("PATCHED: Cross-origin redirect was not followed.")

In versions prior to 1.30.0 and 2.2.0, executing this test populates the leaked list with a request to untrusted.example containing both `

Impact Assessment

The primary impact of CVE-2026-116685 is unauthorized disclosure of sensitive authentication credentials and confidential application data (Confidentiality: High). In enterprise MCP deployments, clients frequently authenticate to remote tool servers using static API keys (X-API-Key), service-mesh tokens, or custom proxy headers. If these credentials are leaked to an external origin via a redirect, an attacker can use them to authenticate directly against the legitimate MCP server, invoke privileged tools, or access backend resources associated with the client's identity.

Beyond credential exposure, the replay of POST bodies during 307 and 308 redirects exposes the contents of JSON-RPC messages (initialize, tools/call, resources/read, prompts/get). Because MCP is designed to pass context, user prompts, database queries, and file contents between host applications and remote servers, intercepting these request bodies gives an attacker direct visibility into sensitive operational data. Similarly, in OAuth-enabled workflows, cross-origin redirects during dynamic client registration or token requests can expose client metadata and authorization parameters.

The vulnerability is scored at CVSS v3.1 5.9 (Medium) with the vector CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:N/A:N. The Attack Complexity (AC:H) metric reflects that an attacker cannot trigger the vulnerability autonomously against an arbitrary client; exploitation depends on preconditions outside the client's immediate control, such as an open redirect on the trusted server, a misconfigured reverse proxy, DNS/domain takeover of a retired redirect target, or an active man-in-the-middle position. Integrity and Availability metrics are rated as None (I:N/A:N) because the redirect mechanism itself only discloses data and does not allow modifying client state or disrupting service beyond connection failure.

Remediation

To remediate CVE-2026-116685, upgrade the mcp package to version 1.30.0 (for projects on the 1.x release line) or 2.2.0 (for projects on the 2.x release line). The patched releases enforce strict origin checks on all HTTP redirects across streamable_http_client, streamablehttp_client, sse_client, ClientSessionGroup, and OAuth flows without requiring any changes to application code.

# For applications using the 1.x release series:
pip install --upgrade "mcp>=1.30.0,<2.0.0"
 
# For applications using the 2.x release series:
pip install --upgrade "mcp>=2.2.0"

> [!IMPORTANT] > After upgrading, if a server returns a cross-origin redirect or an HTTPS-to-HTTP downgrade redirect, the SDK will refuse to follow it and will raise an httpx.HTTPStatusError (in v1.30.0+) or an MCPError with code INVALID_REQUEST (in v2.2.0+). If yourMCP server sits behind a TLS-terminating reverse proxy that issues relative or http:// redirects on trailing slashes (e.g., /mcp to http://host/mcp/), configure the server proxy to trust X-Forwarded-Proto headers or configure the client URL to match the exact canonical path.

For environments where an immediate package upgrade is not feasible, developers can mitigate the issue by passing a custom httpx.AsyncClient instance with follow_redirects=False explicitly configured:

import httpx
from mcp.client.streamable_http import streamable_http_client
 
# Workaround for mcp < 1.30.0 / < 2.2.0:
# Supply a custom AsyncClient with follow_redirects=False
custom_client = httpx.AsyncClient(
    headers={"X-API-Key": "your-api-key"},
    timeout=httpx.Timeout(30.0, read=300.0),
    follow_redirects=False,
)
 
async with streamable_http_client("https://mcp.example.com/mcp", http_client=custom_client) as (read, write, _):
    ...

When using sse_client or streamablehttp_client in v1.x, pass a custom httpx_client_factory callable that returns an httpx.AsyncClient initialized with follow_redirects=False. Finally, if any MCP client instances in your environment connected to endpoints with untrusted or third-party redirect rules while configured with custom credential headers, rotate the affected API keys and tokens immediately.

Official Patches

modelcontextprotocolOfficial GitHub Security Advisory GHSA-5h93-6whr-6q8j
modelcontextprotocolMCP Python SDK v1.30.0 Release
modelcontextprotocolMCP Python SDK v2.2.0 Release

Fix Analysis (3)

Technical Appendix

CVSS Score
5.9/ 10
CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:N/A:N

Affected Systems

Model Context Protocol (MCP) Python SDK (`mcp` PyPI package)

Affected Versions Detail

Product
Affected Versions
Fixed Version
mcp (Python SDK)
modelcontextprotocol
>= 1.8.0, < 1.30.01.30.0
mcp (Python SDK)
modelcontextprotocol
>= 2.0.0, < 2.2.02.2.0
AttributeDetail
CVE IDCVE-2026-116685 (GHSA-5h93-6whr-6q8j)
Weakness ClassCWE-200: Exposure of Sensitive Information to an Unauthorized Actor
CVSS v3.1 Score5.9 Medium (CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:N/A:N)
Affected Packagemcp (PyPI) >= 1.8.0, < 1.30.0 and >= 2.0.0, < 2.2.0
Patched Versions1.30.0 (1.x branch) and 2.2.0 (2.x branch)
Attack VectorNetwork (Cross-Origin HTTP 3xx Redirects on MCP Client Transports)
Primary ImpactLeakage of custom credential headers (e.g., X-API-Key) and HTTP 307/308 POST bodies
CISA KEV StatusNot Listed

MITRE ATT&CK Mapping

T1552Unsecured Credentials
Credential Access
T1005Data from Local System
Collection
CWE-200
Exposure of Sensitive Information to an Unauthorized Actor

The product exposes sensitive information to an actor that is not explicitly authorized to have access to that information. Specifically, sensitive custom HTTP authentication headers and JSON-RPC POST request bodies are forwarded across origin boundaries during automatic HTTP redirect handling.

Vulnerability Timeline

Fix commit c6762e821c527925f0b617db216d00fbd1d0bf99 merged to main branch via PR #3397 for v2.x.
2026-09-04
Fix commit 2106335745563b2321b8c73fef2c12903d00aa6e backported to v1.x branch via PR #3448, followed by userinfo refinement commit 9771e6b59c775ecb2584849d389ce9efba23a541 (PR #3450).
2026-09-05
CVE-2026-116685 and GitHub Security Advisory GHSA-5h93-6whr-6q8j officially published alongside patched releases v1.30.0 and v2.2.0.
2026-10-27

References & Sources

  • [1]GitHub Security Advisory GHSA-5h93-6whr-6q8j
  • [2]NVD - CVE-2026-116685 Detail
  • [3]CVE.org Record: CVE-2026-116685
  • [4]GitHub Pull Request #3397: Restrict HTTP client redirects to the endpoint origin (v2.x)
  • [5]GitHub Pull Request #3448: Restrict HTTP client redirects to the endpoint origin (v1.x)
  • [6]Fix Commit c6762e821c527925f0b617db216d00fbd1d0bf99 (main / v2.2.0)
  • [7]Fix Commit 2106335745563b2321b8c73fef2c12903d00aa6e (v1.x / v1.30.0)
  • [8]Refinement Commit 9771e6b59c775ecb2584849d389ce9efba23a541 (Userinfo preservation)
  • [9]MCP Python SDK Release v1.30.0
  • [10]MCP Python SDK Release v2.2.0

Attack Flow Diagram

Press enter or space to select a node. You can then use the arrow keys to move the node around. Press delete to remove it and escape to cancel.
Press enter or space to select an edge. You can then press delete to remove it or escape to cancel.

More Reports

•about 1 hour ago•CVE-2026-116686
6.5

CVE-2026-116686: Server-Side Request Forgery and Synchronous Denial of Service in Model Context Protocol Python SDK

CVE-2026-116686 is a Server-Side Request Forgery (SSRF) and Denial of Service (DoS) vulnerability in the official Model Context Protocol (MCP) Python SDK (mcp package on PyPI). When an MCP client validates structured tool execution results against a server-provided outputSchema, the SDK invokes the Python jsonschema library with its default URI resolution configuration. An untrusted or compromised MCP server can supply an outputSchema containing external $ref directives (using http://, https://, or file:// schemes), forcing the client process to synchronously fetch internal network resources, read local files, or block the main event loop indefinitely.

Amit Schendel
Amit Schendel
1 views•10 min read
•about 3 hours ago•CVE-2026-116694
6.3

CVE-2026-116694: Unbounded Memory Allocation and Denial of Service in OpenTelemetry Python Jaeger Propagator

CVE-2026-116694 (GHSA-f5m9-jfrj-jjj7) is an unbounded resource allocation vulnerability (CWE-770) in the optional Jaeger propagator component (opentelemetry-propagator-jaeger) of the OpenTelemetry Python SDK prior to version 1.45.0. When extracting distributed tracing context from inbound carriers, JaegerPropagator.extract() processes all headers prefixed with 'uberctx-' without enforcing limits on entry count, per-entry byte size, or aggregate byte size. In environments where transport-level header constraints are absent, relaxed, or bypassed (such as non-HTTP message brokers, RPC frameworks, or web servers with elevated buffer configurations), an unauthenticated remote attacker can supply high-volume or oversized baggage headers to trigger excessive URL unquoting, short-lived immutable dictionary allocations, and CPU starvation.

Alon Barad
Alon Barad
3 views•10 min read
•about 4 hours ago•CVE-2026-116684
6.8

CVE-2026-116684: Resource-Confusion Authorization Bypass in Model Context Protocol Python SDK

CVE-2026-116684 is an incorrect authorization vulnerability (CWE-863) in the Model Context Protocol (MCP) Python SDK (`modelcontextprotocol/python-sdk`). The server-side bearer authentication middleware (`BearerAuthBackend`) verifies token cryptographic signatures and expiration timestamps via `TokenVerifier`, but fails to verify that the token's audience (`aud` claim or RFC 8707 resource indicator) matches the receiving MCP server's configured `resource_server_url`. In multi-service environments sharing a single OAuth 2.0 Authorization Server, an attacker possessing a valid token for an unrelated service can replay it against the MCP server to gain unauthorized access to protected tools, resources, and prompts.

Amit Schendel
Amit Schendel
5 views•9 min read
•about 5 hours ago•CVE-2026-116675
8.5

CVE-2026-116675: Stored Cross-Site Scripting in TinyMCE Media Plugin via Pre-Sanitization DOM Instantiation

CVE-2026-116675 is a stored Cross-Site Scripting (XSS) vulnerability in the TinyMCE rich text editor affecting versions 7.9.3 and 8.5.1 through 8.9.2. The flaw resides in the media plugin's serialization logic, where placeholder elements configured with the data-mce-object attribute are converted into real DOM elements using the active window's document context prior to sanitization. When an attacker supplies a media element with an invalid source attribute alongside an inline event handler attribute such as data-mce-p-onerror, the browser resolves the resource and executes the malicious JavaScript before the sanitizer can strip the dangerous attributes.

Alon Barad
Alon Barad
5 views•10 min read
•about 6 hours ago•CVE-2026-116693
8.7

CVE-2026-116693: Regular Expression Denial of Service in Datadog Node.js Tracer (dd-trace)

CVE-2026-116693 is a high-severity Regular Expression Denial of Service (ReDoS) vulnerability affecting the official Datadog Application Performance Monitoring (APM) client library for Node.js, dd-trace. The defect resides in the default regular expression defined by the DD_TRACE_OBFUSCATION_QUERY_STRING_REGEXP configuration parameter, which is used to sanitize incoming and outgoing HTTP URL query strings prior to recording trace span metadata. Due to overlapping sub-patterns and unanchored repetition blocks in the JSON Web Token (JWT) and URL-encoded string matching branches, the V8 JavaScript engine's regular expression subsystem (Irregexp) can be forced into catastrophic or high-degree polynomial backtracking. Because regular expression replacement occurs synchronously on the primary Node.js event loop, an unauthenticated remote attacker can send crafted HTTP requests with malicious query strings to consume 100% of the process CPU core, stalling concurrent request processing and rendering the application unavailable.

Alon Barad
Alon Barad
5 views•10 min read
•about 7 hours ago•CVE-2026-116692
9.8

CVE-2026-116692: Remote Code Execution in MLflow via Third-Party Scorer Deserialization

CVE-2026-116692 (GHSA-26p8-2jq9-3vq9) is a remote code execution vulnerability in MLflow affecting versions 3.12.0rc0 prior to 3.17.0. The flaw stems from an overly permissive module prefix check during the deserialization of third-party GenAI evaluation scorers in mlflow/genai/scorers/base.py. By setting an experiment's artifact root to a local package directory within the Python module search path and uploading a crafted Python file as a run artifact, an attacker can invoke the /ajax-api/3.0/mlflow/scorer/invoke endpoint to dynamically import and execute arbitrary code on the MLflow tracking server.

Amit Schendel
Amit Schendel
9 views•9 min read