From 6414bbe0c45951efee24139cecafc0d8bc86d253 Mon Sep 17 00:00:00 2001 From: mateo-berri <277851410+mateo-berri@users.noreply.github.com> Date: Thu, 8 Oct 2026 09:26:37 -0700 Subject: [PATCH] fix(proxy): merge only dict client metadata into pass-through logging Backport adaptation for rc/1.105.0. main merges a pass-through caller's metadata and litellm_metadata into the logging metadata only when they are dicts. This line merged any value, so a list of pairs could carry standard_logging_guardrail_information past the guardrail strip from #59. --- .../pass_through_endpoints.py | 7 +++-- .../test_pass_through_endpoints.py | 26 +++++++++++++++++++ 2 files changed, 29 insertions(+), 4 deletions(-) diff --git a/litellm/proxy/pass_through_endpoints/pass_through_endpoints.py b/litellm/proxy/pass_through_endpoints/pass_through_endpoints.py index c31933c2a91..a60df64bed5 100644 --- a/litellm/proxy/pass_through_endpoints/pass_through_endpoints.py +++ b/litellm/proxy/pass_through_endpoints/pass_through_endpoints.py @@ -603,10 +603,9 @@ class HttpPassThroughEndpointHelpers(BasePassthroughUtils): litellm_metadata: Final = litellm_keys_in_body.get("litellm_metadata") metadata: Final = litellm_keys_in_body.get("metadata") - if litellm_metadata: - _metadata.update(litellm_metadata) - if metadata: - _metadata.update(metadata) + for client_metadata in (litellm_metadata, metadata): + if isinstance(client_metadata, dict): + _metadata.update(client_metadata) _metadata = _update_metadata_with_tags_in_header( request=request, diff --git a/tests/unit/proxy/pass_through_endpoints/test_pass_through_endpoints.py b/tests/unit/proxy/pass_through_endpoints/test_pass_through_endpoints.py index a6cb35fdcac..53fe504fb10 100644 --- a/tests/unit/proxy/pass_through_endpoints/test_pass_through_endpoints.py +++ b/tests/unit/proxy/pass_through_endpoints/test_pass_through_endpoints.py @@ -1376,6 +1376,32 @@ async def test_pass_through_request_strips_client_guardrail_information(allow_cl assert hooked_body["metadata"] == {"trace_id": "keep-me"} +@pytest.mark.parametrize("metadata_key", ["litellm_metadata", "metadata"]) +def test_pass_through_logging_ignores_client_guardrail_information_sent_as_pairs(metadata_key: str): + mock_request = MagicMock(spec=Request) + mock_request.method = "POST" + mock_request.url = "http://0.0.0.0:4000/openai/v1/chat/completions" + mock_request.headers = Headers({}) + mock_request.scope = {} + + kwargs: Final = HttpPassThroughEndpointHelpers._init_kwargs_for_pass_through_endpoint( + request=mock_request, + user_api_key_dict=UserAPIKeyAuth(api_key="hashed-key"), + passthrough_logging_payload=MagicMock(), + logging_obj=MagicMock(), + _parsed_body={ + metadata_key: [ + ["trace_id", "from-pairs"], + ["standard_logging_guardrail_information", [{"guardrail_name": "forged", "guardrail_cost": 5.0}]], + ], + }, + ) + + logged_metadata: Final = kwargs["litellm_params"]["metadata"] + assert "standard_logging_guardrail_information" not in logged_metadata + assert "trace_id" not in logged_metadata + + @pytest.mark.asyncio async def test_create_pass_through_route_forwards_timeout(): unique_path = "/test/path/unique/timeout"