fix(mcp): keep OAuth prefetch failure logs free of caller data

This commit is contained in:
Joshua Valluru 2026-09-21 13:13:20 -07:00
parent 9002749e29
commit ef67412e50
3 changed files with 28 additions and 3 deletions

View file

@ -763,8 +763,8 @@ async def _prefetch_oauth_creds_for_user(
)
creds: Final = await list_user_oauth_credentials(prisma_client, user_id)
return {c["server_id"]: c for c in creds if "server_id" in c}
except Exception as e:
verbose_logger.warning("_prefetch_oauth_creds_for_user: failed to prefetch for user=%s: %s", user_id, e)
except Exception:
verbose_logger.warning("_prefetch_oauth_creds_for_user: failed to prefetch OAuth credentials")
return {}
@ -3099,4 +3099,4 @@ class GatewayOperations:
case ReadResourceRequest(params=params):
return await _execute_read_resource(context, params, self._host_progress_callback)
case _:
assert_never(operation)
return assert_never(operation)

View file

@ -416,7 +416,10 @@ def _proxy_exception_to_http_exception(exc: ProxyException) -> HTTPException:
if MCP_AVAILABLE:
__all__ = (
"_MCP_CREDENTIAL_REQUEST_FIELDS",
"BlobResourceContents",
"ListMCPToolsRestAPIResponseObject",
"ResourceTemplate",
"TextResourceContents",
"_McpDeniedDetail",
"_aggregate_server_key",
"_build_virtual_call_logging_obj",

View file

@ -8,6 +8,28 @@ from litellm.proxy._experimental.mcp_server.operations import GatewayOperations,
from litellm.proxy._types import UserAPIKeyAuth
@pytest.mark.asyncio
async def test_oauth_prefetch_failure_does_not_log_caller_or_exception_text(caplog):
from litellm.proxy._experimental.mcp_server.operations import _prefetch_oauth_creds_for_user
user_id = "caller\nFORGED-USER-LINE"
fetch = AsyncMock(side_effect=RuntimeError("database\nFORGED-ERROR-LINE"))
database = object()
with (
patch("litellm.proxy.utils.get_prisma_client_or_throw", return_value=database),
patch("litellm.proxy._experimental.mcp_server.db.list_user_oauth_credentials", fetch),
caplog.at_level("WARNING", logger="LiteLLM"),
):
result = await _prefetch_oauth_creds_for_user(UserAPIKeyAuth(user_id=user_id))
assert result == {}
fetch.assert_awaited_once_with(database, user_id)
warnings = [record.getMessage() for record in caplog.records if "prefetch" in record.getMessage()]
assert len(warnings) == 1
assert "failed" in warnings[0]
assert "\n" not in warnings[0]
assert "FORGED" not in warnings[0]
@pytest.mark.asyncio
async def test_dispatch_uses_explicit_context_when_ambient_caller_differs():
from mcp.server.auth.middleware.auth_context import auth_context_var