diff --git a/litellm/utils.py b/litellm/utils.py index ef67ea74894..48b0bd87fc9 100644 --- a/litellm/utils.py +++ b/litellm/utils.py @@ -7402,9 +7402,11 @@ def print_args_passed_to_litellm(original_function, args, kwargs): def get_logging_id(start_time, response_obj): try: raw_id = response_obj.get("id") or "" - # Batch API IDs may be S3 URIs (e.g. "s3://bucket/key"). Strip the scheme and bucket, keeping only the object key to use as the log ID. + # Batch API IDs may be S3 URIs (e.g. "s3://bucket/key"). Strip the + # scheme and bucket, keeping only the object key to use as the log ID. if "://" in raw_id: - safe_id = raw_id.split("://", 1)[1].split("/", 1)[-1].replace("/", "-") + after_scheme = raw_id.split("://", 1)[1] # "bucket/key" or "bucket" + safe_id = after_scheme.split("/", 1)[1].replace("/", "-") if "/" in after_scheme else "" else: safe_id = raw_id response_id = "time-" + start_time.strftime("%H-%M-%S-%f") + "_" + safe_id diff --git a/tests/test_litellm/integrations/test_s3_v2.py b/tests/test_litellm/integrations/test_s3_v2.py index 7dc25043fd5..ce69dad3887 100644 --- a/tests/test_litellm/integrations/test_s3_v2.py +++ b/tests/test_litellm/integrations/test_s3_v2.py @@ -687,6 +687,24 @@ def test_get_logging_id_normal_id_unchanged(): assert result == "time-17-40-11-901585_chatcmpl-abc123" +def test_get_logging_id_bucket_only_uri_does_not_leak_bucket_name(): + """s3://my-bucket with no object key must not leak the bucket name into the log path.""" + start_time = datetime(2026, 3, 9, 17, 40, 11, 901585) + response_obj = {"id": "s3://my-bucket"} + result = get_logging_id(start_time, response_obj) + assert "my-bucket" not in result, "Bucket name must not appear in log ID" + assert "://" not in result + + +def test_get_logging_id_none_id_does_not_raise(): + """None id must not raise and must return a usable (non-None) string.""" + start_time = datetime(2026, 3, 9, 17, 40, 11, 901585) + response_obj = {"id": None} + result = get_logging_id(start_time, response_obj) + assert result is not None + assert result.startswith("time-17-40-11-901585_") + + def test_get_logging_id_s3_uri_safe_for_url_path(): """The sanitized log ID must be embeddable in an S3 object key URL without creating a malformed path.""" start_time = datetime(2026, 3, 9, 17, 40, 11, 901585)