From a24aedd7839b12e065482120ac3e6e6bcc29c3a7 Mon Sep 17 00:00:00 2001 From: pjdurden Date: Thu, 20 Aug 2026 21:41:11 -0500 Subject: [PATCH] fix: reject non-positive session_ttl_seconds on sensitive_data_routing A non-positive TTL either expires the in-memory pin immediately or makes Redis reject the SETEX, so sticky_session silently never pinned. Bound the field at config-parse time instead of failing quietly at request time. Signed-off-by: pjdurden --- .../guardrail_hooks/sensitive_data_routing.py | 1 + .../test_sensitive_data_routing.py | 15 +++++++++++++++ 2 files changed, 16 insertions(+) diff --git a/litellm/types/proxy/guardrails/guardrail_hooks/sensitive_data_routing.py b/litellm/types/proxy/guardrails/guardrail_hooks/sensitive_data_routing.py index 0c71d41101c..65aa4c077cf 100644 --- a/litellm/types/proxy/guardrails/guardrail_hooks/sensitive_data_routing.py +++ b/litellm/types/proxy/guardrails/guardrail_hooks/sensitive_data_routing.py @@ -34,6 +34,7 @@ class SensitiveDataRoutingGuardrailConfigModel(GuardrailConfigModel): ) session_ttl_seconds: int = Field( default=DEFAULT_SESSION_TTL_SECONDS, + ge=1, description="How long a session stays pinned to the on-premise model after detection.", ) diff --git a/tests/test_litellm/proxy/guardrails/guardrail_hooks/test_sensitive_data_routing.py b/tests/test_litellm/proxy/guardrails/guardrail_hooks/test_sensitive_data_routing.py index 78508278481..b913d99b97d 100644 --- a/tests/test_litellm/proxy/guardrails/guardrail_hooks/test_sensitive_data_routing.py +++ b/tests/test_litellm/proxy/guardrails/guardrail_hooks/test_sensitive_data_routing.py @@ -1,6 +1,7 @@ """Tests for the built-in Sensitive Data Routing guardrail.""" import pytest +from pydantic import ValidationError from litellm.exceptions import SensitiveDataRouteException from litellm.proxy.guardrails.guardrail_hooks.sensitive_data_routing import ( @@ -13,6 +14,9 @@ from litellm.proxy.guardrails.guardrail_registry import ( guardrail_initializer_registry, ) from litellm.types.guardrails import GuardrailEventHooks, LitellmParams +from litellm.types.proxy.guardrails.guardrail_hooks.sensitive_data_routing import ( + SensitiveDataRoutingGuardrailConfigModel, +) DOCUMENTED_LITELLM_PARAMS = { "guardrail": "sensitive_data_routing", @@ -65,6 +69,17 @@ class TestSensitiveDataRoutingGuardrailRegistration: with pytest.raises(ValueError, match="Unknown pattern name"): make_guardrail(prebuilt_patterns=["not_a_real_pattern"]) + @pytest.mark.parametrize("ttl", [0, -1]) + def test_non_positive_session_ttl_is_rejected(self, ttl): + """A non-positive TTL expires the pin immediately, so reject it at config time + instead of silently never pinning the session.""" + with pytest.raises(ValidationError): + SensitiveDataRoutingGuardrailConfigModel( + on_premise_model="on-prem-model", + keywords=["confidential"], + session_ttl_seconds=ttl, + ) + class TestSensitiveDataRoutingGuardrailDetection: @pytest.mark.asyncio