mirror of
https://github.com/BerriAI/litellm.git
synced 2026-09-12 23:01:41 +00:00
* fix(mcp): drop caller host and configured upstream headers from logged metadata The synthetic request that carries MCP client headers into add_litellm_data_to_request forwarded the caller's Host header, and Request.url is built from it, so a caller chose the proxy_server_request url and the metadata endpoint that every logging callback records. _upstream_credential_headers also only knew the configured client side auth header and the x-mcp- prefix family, so a header name declared in mcp_servers.<name>.extra_headers reached logging metadata in cleartext. Those names are admin chosen, so no prefix rule can recognize them; read them off the server registry instead. The header is still forwarded upstream, which is what extra_headers is for. authorization is left out because clean_headers already strips it and claiming it here would move authenticated_with_header on the oauth passthrough config. The Responses bridge tests stub the server manager, so their fakes gain the registry accessor the sanitizer now reads. * fix(mcp): drop caller host from the sanitized header mapping too The synthetic request stopped forwarding host, but the parallel sanitizer did not, so a forged hostname still reached the guardrail payload and the list_tools spend row. Drop it there as well. Exempt the configured identity headers from the upstream credential set. get_user_from_headers resolves end user attribution off the same request this module reconstructs, and it only fills end_user_id when auth left it unset, so claiming user_header_name or a user_header_mappings name would lose attribution on the MCP paths that authenticate upstream. Drop the isinstance guard on extra_headers entries: the field is typed list[str], so the check is dead and basedpyright scores it. * fix(mcp): accept a bare user_header_mappings entry when exempting identity headers get_internal_user_header_from_mapping and get_customer_user_header_from_mapping both normalize a single mapping to a one element list, and config_settings.md documents the key as a dict. Iterating the bare form yields its keys instead, so the exemption silently matched nothing and an identity header also named in an MCP server's extra_headers was dropped after all. |
||
|---|---|---|
| .. | ||
| litellm_completion_transformation | ||
| mcp | ||
| test_custom_tool_call.py | ||
| test_metadata_codex_callback.py | ||
| test_no_duplicate_spend_logs.py | ||
| test_null_test_fix.py | ||
| test_responses_api_bridge_flag.py | ||
| test_responses_api_request_body.py | ||
| test_responses_prompt_management.py | ||
| test_responses_router_cooldown.py | ||
| test_responses_streaming_iterator.py | ||
| test_responses_utils.py | ||
| test_responses_websocket_all_providers.py | ||
| test_rust_bridge_websocket.py | ||
| test_sse_output_recovery.py | ||
| test_streaming_iterator.py | ||
| test_streaming_iterator_error_events.py | ||
| test_text_format_conversion.py | ||