From de7ebd871b25104143e13341ee59ccce515de38e Mon Sep 17 00:00:00 2001 From: Tanvir Alam Date: Mon, 28 Sep 2026 00:34:58 -0400 Subject: [PATCH] fix(proxy): tolerate missing team_id in responses id decrypt _decrypt_response_id required parts[2] after only checking len(parts) >= 2, so a two-segment managed id (response_id + user_id, no team) raised IndexError and broke follow-up /v1/responses calls. Treat team_id as optional when the third segment is absent. Fixes #43493 --- litellm/proxy/hooks/responses_id_security.py | 12 ++++++++---- tests/unit/test_responses_id_security.py | 19 +++++++++++++++++++ 2 files changed, 27 insertions(+), 4 deletions(-) diff --git a/litellm/proxy/hooks/responses_id_security.py b/litellm/proxy/hooks/responses_id_security.py index bdf7e2ab53d..d63090a3bad 100644 --- a/litellm/proxy/hooks/responses_id_security.py +++ b/litellm/proxy/hooks/responses_id_security.py @@ -244,7 +244,9 @@ class ResponsesIDSecurity(CustomLogger): return response_id, None, None if decrypted_value.startswith(SpecialEnums.LITELM_MANAGED_FILE_ID_PREFIX.value): - # Expected format: "litellm_proxy:responses_api:response_id:{response_id};user_id:{user_id}" + # Formats: + # - "litellm_proxy:responses_api:response_id:{id};user_id:{user};team_id:{team}" + # - "litellm_proxy:responses_api:response_id:{id};user_id:{user}" (legacy / no team) parts: Final = decrypted_value.split(";") if len(parts) >= 2: @@ -256,9 +258,11 @@ class ResponsesIDSecurity(CustomLogger): user_id_part: Final = parts[1] user_id: Final = user_id_part.split("user_id:")[-1] - # Extract team_id from "team_id:{team_id}" - team_id_part: Final = parts[2] - team_id: Final = team_id_part.split("team_id:")[-1] + # Team segment is optional; older two-segment ids omit it. + team_id: str | None = None + if len(parts) >= 3: + team_id_part: Final = parts[2] + team_id = team_id_part.split("team_id:")[-1] return original_response_id, user_id, team_id else: diff --git a/tests/unit/test_responses_id_security.py b/tests/unit/test_responses_id_security.py index 704a52fc202..c79e18cd4ed 100644 --- a/tests/unit/test_responses_id_security.py +++ b/tests/unit/test_responses_id_security.py @@ -113,6 +113,25 @@ class TestDecryptResponseId: assert team_id is None + def test_decrypt_response_id_two_segment_no_team(self, responses_id_security): + """Two-segment managed ids (no team_id) must not IndexError on parts[2].""" + import litellm.proxy.hooks.responses_id_security as responses_module + + with patch.object(responses_module, "decrypt_value_helper") as mock_decrypt: + mock_decrypt.return_value = ( + f"{SpecialEnums.LITELM_MANAGED_FILE_ID_PREFIX.value}" + "response_id:resp_abc;user_id:user-1" + ) + + original_id, user_id, team_id = responses_id_security._decrypt_response_id( + "resp_encrypted_two_segment" + ) + + assert original_id == "resp_abc" + assert user_id == "user-1" + assert team_id is None + + class TestCheckUserAccessToResponseId: """Test check_user_access_to_response_id function"""