fix(mcp): share invalid MCP client IP sentinel

Define a shared fail-closed MCP client IP sentinel and reuse it across Responses utilities, LazyMCP routing, and tests to avoid security-critical string drift.
This commit is contained in:
jibanez-staticduo 2026-05-13 17:40:04 +02:00
parent 9ce8a2d956
commit 7ba28bb6dd
No known key found for this signature in database
4 changed files with 13 additions and 6 deletions

View file

@ -20,6 +20,7 @@ from litellm.litellm_core_utils.litellm_logging import Logging as LiteLLMLogging
from litellm.proxy._experimental.mcp_server.utils import split_server_prefix_from_name
from litellm.responses.main import aresponses
from litellm.responses.streaming_iterator import BaseResponsesAPIStreamingIterator
from litellm.responses.utils import INVALID_MCP_CLIENT_IP_SENTINEL
from litellm.types.llms.openai import ResponsesAPIResponse
from litellm.types.utils import (
CallTypes,
@ -463,7 +464,7 @@ class LiteLLM_Proxy_MCP_Handler:
)
standard_client_ip = (
None if client_ip == "__invalid_mcp_client_ip__" else client_ip
None if client_ip == INVALID_MCP_CLIENT_IP_SENTINEL else client_ip
)
return await LiteLLM_Proxy_MCP_Handler._get_standard_mcp_tools(
user_api_key_auth=user_api_key_auth,

View file

@ -32,6 +32,8 @@ from litellm.types.utils import (
Usage,
)
INVALID_MCP_CLIENT_IP_SENTINEL = "__invalid_mcp_client_ip__"
class ResponsesAPIRequestUtils:
"""Helper utils for constructing ResponseAPI requests"""
@ -900,7 +902,7 @@ class ResponsesAPIRequestUtils:
client_ip = secret_fields.get("mcp_client_ip")
if isinstance(client_ip, str) and client_ip.strip():
return client_ip.strip()
return "__invalid_mcp_client_ip__"
return INVALID_MCP_CLIENT_IP_SENTINEL
class ResponseAPILoggingUtils:

View file

@ -21,7 +21,10 @@ from litellm.proxy._types import (
MCPTransport,
UserAPIKeyAuth,
)
from litellm.responses.utils import ResponsesAPIRequestUtils
from litellm.responses.utils import (
INVALID_MCP_CLIENT_IP_SENTINEL,
ResponsesAPIRequestUtils,
)
from litellm.types.mcp import MCPAuth
from litellm.types.mcp_server.mcp_server_manager import MCPServer
@ -967,7 +970,7 @@ def test_verified_mcp_client_ip_returns_value_or_fail_closed():
)
assert (
ResponsesAPIRequestUtils.get_verified_mcp_client_ip({})
== "__invalid_mcp_client_ip__"
== INVALID_MCP_CLIENT_IP_SENTINEL
)

View file

@ -10,6 +10,7 @@ import importlib
from litellm.responses.mcp.litellm_proxy_mcp_handler import (
LiteLLM_Proxy_MCP_Handler,
)
from litellm.responses.utils import INVALID_MCP_CLIENT_IP_SENTINEL
from typing import Any, cast
from litellm.types.llms.openai import ResponseAPIUsage, ResponsesAPIResponse
from litellm.types.utils import ModelResponse
@ -354,7 +355,7 @@ async def test_lazymcp_catalog_uses_fail_closed_client_ip(monkeypatch):
client_ip=ResponsesAPIRequestUtils.get_verified_mcp_client_ip(None),
)
assert captured["client_ip"] == "__invalid_mcp_client_ip__"
assert captured["client_ip"] == INVALID_MCP_CLIENT_IP_SENTINEL
@pytest.mark.asyncio
@ -950,7 +951,7 @@ async def test_standard_mcp_preserves_missing_client_ip_behavior(monkeypatch):
mcp_tools_with_litellm_proxy=[
{"type": "mcp", "server_url": "litellm_proxy/mcp/standard"}
],
client_ip="__invalid_mcp_client_ip__",
client_ip=INVALID_MCP_CLIENT_IP_SENTINEL,
)
assert captured["client_ip"] is None