diff --git a/litellm/litellm_core_utils/initialize_dynamic_callback_params.py b/litellm/litellm_core_utils/initialize_dynamic_callback_params.py index 68fa69dbda7..074b446a8ef 100644 --- a/litellm/litellm_core_utils/initialize_dynamic_callback_params.py +++ b/litellm/litellm_core_utils/initialize_dynamic_callback_params.py @@ -36,9 +36,9 @@ _SUPPORTED_CALLBACK_PARAMS_FROZEN = frozenset( ) # List form for iteration (excludes litellm_logging_obj, environment_variables - config only) -_supported_callback_params = [ +_supported_callback_params = sorted( p for p in _SUPPORTED_CALLBACK_PARAMS_FROZEN if p not in ("litellm_logging_obj", "environment_variables") -] +) def scrub_callback_config_params_from_dict(data: Dict) -> Dict: diff --git a/litellm/litellm_core_utils/litellm_logging.py b/litellm/litellm_core_utils/litellm_logging.py index 0e4a9010c38..ed7dd8c65d4 100644 --- a/litellm/litellm_core_utils/litellm_logging.py +++ b/litellm/litellm_core_utils/litellm_logging.py @@ -527,7 +527,10 @@ class Logging(LiteLLMLoggingBaseClass): user: Optional[str] = None, **additional_params, ): - self.optional_params = optional_params + sanitized_optional_params = scrub_callback_config_params_from_dict( + dict(optional_params) + ) + self.optional_params = sanitized_optional_params if model is not None: self.model = model self.user = user @@ -540,9 +543,6 @@ class Logging(LiteLLMLoggingBaseClass): if _is_debugging_on() or self.litellm_request_debug: verbose_logger.debug(f"self.optional_params: {self.optional_params}") - sanitized_optional_params = scrub_callback_config_params_from_dict( - dict(optional_params) - ) self.model_call_details.update( { "model": self.model, diff --git a/tests/logging_callback_tests/test_dynamic_otel_keys.py b/tests/logging_callback_tests/test_dynamic_otel_keys.py index 93e63534288..66960e2c85f 100644 --- a/tests/logging_callback_tests/test_dynamic_otel_keys.py +++ b/tests/logging_callback_tests/test_dynamic_otel_keys.py @@ -65,7 +65,31 @@ def test_scrub_callback_config_params_removes_credentials(): assert "litellm_logging_obj" not in result +def test_scrub_callback_config_params_pattern_matching(): + """Test suffix-pattern scrubbing for custom integration credentials.""" + data = { + "model": "gpt-4", + "temperature": 0.7, + "my_custom_service_api_key": "secret-api-key", + "some_integration_secret": "s3cr3t", + "another_service_secret_key": "sk-xxxx", + "keep_this_value": "important_data", + } + result = scrub_callback_config_params_from_dict(data) + + # Verify safe values are kept + assert "model" in result and result["model"] == "gpt-4" + assert "temperature" in result and result["temperature"] == 0.7 + assert "keep_this_value" in result and result["keep_this_value"] == "important_data" + + # Verify credentials are scrubbed by suffix patterns + assert "my_custom_service_api_key" not in result + assert "some_integration_secret" not in result + assert "another_service_secret_key" not in result + + if __name__ == "__main__": test_dynamic_key_extraction_from_metadata() test_dynamic_key_extraction_from_litellm_params_metadata() test_scrub_callback_config_params_removes_credentials() + test_scrub_callback_config_params_pattern_matching()