From 11fc0038cdc809ef12601a6bd1c5b33c875f90e7 Mon Sep 17 00:00:00 2001 From: King Star Date: Thu, 10 Sep 2026 08:55:36 +0800 Subject: [PATCH] fix(proxy): gate caller-controlled SSL verification --- litellm/proxy/auth/auth_utils.py | 1 + .../proxy/auth/test_auth_utils.py | 47 +++++++++++++++++++ .../auth/test_banned_params_extra_body.py | 1 + 3 files changed, 49 insertions(+) diff --git a/litellm/proxy/auth/auth_utils.py b/litellm/proxy/auth/auth_utils.py index f78c4221f5a..0619c35b40a 100644 --- a/litellm/proxy/auth/auth_utils.py +++ b/litellm/proxy/auth/auth_utils.py @@ -350,6 +350,7 @@ _BANNED_REQUEST_BODY_PARAMS: Final[tuple[str, ...]] = ( # the request away from the admin's pinned configuration. "nvcf_function_id", "use_ssl", + "ssl_verify", # Per-deployment opt-in that hands the whole call to the Rust core. It is a # deployment decision, not a request one: the Rust path uses its own client # rather than the one the deployment configured, and reports no post_call, diff --git a/tests/test_litellm/proxy/auth/test_auth_utils.py b/tests/test_litellm/proxy/auth/test_auth_utils.py index aaf630ad29b..3906fb3aad0 100644 --- a/tests/test_litellm/proxy/auth/test_auth_utils.py +++ b/tests/test_litellm/proxy/auth/test_auth_utils.py @@ -2329,6 +2329,53 @@ class TestIsRequestBodySafeBlocksEndpointTargetingFields: ) +class TestIsRequestBodySafeBlocksTLSVerificationOverride: + @pytest.mark.parametrize("ssl_verify", [False, "/tmp/custom-ca.pem"]) + def test_ssl_verify_in_request_body_is_rejected(self, ssl_verify): + with pytest.raises(ValueError, match="ssl_verify"): + is_request_body_safe( + request_body={"model": "gpt-4", "ssl_verify": ssl_verify}, + general_settings={}, + llm_router=None, + model="gpt-4", + ) + + def test_admin_opt_in_proxy_wide_allows_ssl_verify(self): + assert ( + is_request_body_safe( + request_body={"model": "gpt-4", "ssl_verify": False}, + general_settings={"allow_client_side_credentials": True}, + llm_router=None, + model="gpt-4", + ) + is True + ) + + def test_admin_opt_in_per_deployment_allows_ssl_verify(self): + from litellm import Router + + router = Router( + model_list=[ + { + "model_name": "gpt-4", + "litellm_params": { + "model": "openai/gpt-4", + "configurable_clientside_auth_params": ["ssl_verify"], + }, + } + ] + ) + assert ( + is_request_body_safe( + request_body={"model": "gpt-4", "ssl_verify": "/tmp/custom-ca.pem"}, + general_settings={}, + llm_router=router, + model="gpt-4", + ) + is True + ) + + class TestIsRequestBodySafeBlocksBedrockProjectOverride: """``aws_bedrock_project_id`` pins a deployment to a Bedrock project so that project's data-retention policy applies to its requests. A diff --git a/tests/test_litellm/proxy/auth/test_banned_params_extra_body.py b/tests/test_litellm/proxy/auth/test_banned_params_extra_body.py index e87b206a40a..8e9ccd4a3b8 100644 --- a/tests/test_litellm/proxy/auth/test_banned_params_extra_body.py +++ b/tests/test_litellm/proxy/auth/test_banned_params_extra_body.py @@ -28,6 +28,7 @@ from litellm.proxy.auth.auth_utils import is_request_body_safe # noqa: E402 "base_url", "vertex_credentials", "azure_ad_token", + "ssl_verify", ], ) def test_banned_param_under_extra_body_is_rejected(banned_param):