From f49ac24c0c0304ee23ae319354fcfe7b09b1db59 Mon Sep 17 00:00:00 2001 From: jesus Date: Tue, 3 Nov 2026 23:09:33 +0000 Subject: [PATCH] fix(masker): keep odd-cased plain names like sEt-CoOkIe sensitive alongside the camelCase split --- litellm/litellm_core_utils/sensitive_data_masker.py | 11 ++++++----- .../litellm_core_utils/test_sensitive_data_masker.py | 5 +++++ 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/litellm/litellm_core_utils/sensitive_data_masker.py b/litellm/litellm_core_utils/sensitive_data_masker.py index 2cf8899cf3a..117c96c06e3 100644 --- a/litellm/litellm_core_utils/sensitive_data_masker.py +++ b/litellm/litellm_core_utils/sensitive_data_masker.py @@ -88,11 +88,12 @@ class SensitiveDataMasker: if excluded_keys and key in excluded_keys: return False - # Split on underscores, hyphens and camelCase boundaries and check if any segment matches the pattern - # This avoids false positives like "max_tokens" matching "token" - # but still catches "api_key", "access_token", "apiKey", "clientSecret", etc. - key_lower: Final = _CAMEL_BOUNDARY.sub("_", str(key)).lower() - key_segments: Final = key_lower.replace("-", "_").split("_") + # Split on underscores and hyphens, and separately on camelCase boundaries, then check whether any + # segment matches the pattern. This avoids false positives like "max_tokens" matching "token" + # but still catches "api_key", "access_token", "apiKey", "clientSecret" and odd-cased "sEt-CoOkIe". + key_lower: Final = str(key).lower().replace("-", "_") + camel_lower: Final = _CAMEL_BOUNDARY.sub("_", str(key)).lower().replace("-", "_") + key_segments: Final = frozenset(key_lower.split("_")) | frozenset(camel_lower.split("_")) # If any segment matches a non-sensitive override, the key is not sensitive. # For example, "input_cost_per_token" contains "token" but also "cost", diff --git a/tests/unit/litellm_core_utils/test_sensitive_data_masker.py b/tests/unit/litellm_core_utils/test_sensitive_data_masker.py index 9039ab99371..b8602954cec 100644 --- a/tests/unit/litellm_core_utils/test_sensitive_data_masker.py +++ b/tests/unit/litellm_core_utils/test_sensitive_data_masker.py @@ -626,6 +626,11 @@ def test_is_sensitive_key_camel_case_split_keeps_pricing_and_count_fields_clear( assert masker.is_sensitive_key("inputCostPerToken") is False +@pytest.mark.parametrize("key", ["sEt-CoOkIe", "AUTHORIZATION", "Api-Key", "X-API-KEY"]) +def test_is_sensitive_key_camel_case_split_does_not_break_odd_cased_plain_names(key: str): + assert SensitiveDataMasker().is_sensitive_key(key) is True + + def test_empty_non_sensitive_overrides_disables_the_cost_exemption(): strict = SensitiveDataMasker(non_sensitive_overrides=frozenset())