Implementation:BerriAI Litellm Sensitive Data Masker
| Attribute | Value |
|---|---|
| Sources | litellm/litellm_core_utils/sensitive_data_masker.py |
| Domains | Security, Logging, Data Masking |
| Last Updated | 2026-02-15 16:00 GMT |
Overview
Recursively masks sensitive values in dictionaries based on key name pattern matching, preserving structure while hiding secrets for safe logging.
Description
The SensitiveDataMasker class detects sensitive dictionary keys by matching key name segments against a configurable set of patterns (e.g., "password", "secret", "key", "token", "auth"). Key matching is segment-based: keys are split on underscores and hyphens, and each segment is checked against the pattern set. This avoids false positives (e.g., "max_tokens" does not match "token" because "tokens" is the segment, not "token").
Sensitive string values are partially masked, showing a configurable number of prefix and suffix characters with the middle replaced by a mask character (default: *). The masker recursively processes nested dictionaries, lists, and objects with __dict__ attributes, with depth limiting to prevent infinite recursion. Keys can be excluded from masking via an excluded_keys set.
Usage
Import SensitiveDataMasker when logging configuration dictionaries, environment variables, or API parameters that may contain secrets. Commonly used in debug logging and error reporting to prevent credential leakage.
Code Reference
Source Location
litellm/litellm_core_utils/sensitive_data_masker.py (148 lines)
Signature
class SensitiveDataMasker:
def __init__(
self,
sensitive_patterns: Optional[Set[str]] = None,
visible_prefix: int = 4,
visible_suffix: int = 4,
mask_char: str = "*",
)
def _mask_value(self, value: str) -> str
def is_sensitive_key(
self, key: str, excluded_keys: Optional[Set[str]] = None
) -> bool
def _mask_sequence(
self,
values: List[Any],
depth: int,
max_depth: int,
excluded_keys: Optional[Set[str]],
key_is_sensitive: bool,
) -> List[Any]
def mask_dict(
self,
data: Dict[str, Any],
depth: int = 0,
max_depth: int = DEFAULT_MAX_RECURSE_DEPTH_SENSITIVE_DATA_MASKER,
excluded_keys: Optional[Set[str]] = None,
) -> Dict[str, Any]
Import
from litellm.litellm_core_utils.sensitive_data_masker import SensitiveDataMasker
I/O Contract
__init__
| Direction | Name | Type | Description |
|---|---|---|---|
| Input | sensitive_patterns | Optional[Set[str]] |
Set of key segment patterns to treat as sensitive (default includes "password", "secret", "key", "token", "auth", etc.) |
| Input | visible_prefix | int |
Number of leading characters to leave visible (default: 4) |
| Input | visible_suffix | int |
Number of trailing characters to leave visible (default: 4) |
| Input | mask_char | str |
Character used for masking (default: *)
|
mask_dict
| Direction | Name | Type | Description |
|---|---|---|---|
| Input | data | Dict[str, Any] |
Dictionary to mask |
| Input | depth | int |
Current recursion depth (default: 0) |
| Input | max_depth | int |
Maximum recursion depth |
| Input | excluded_keys | Optional[Set[str]] |
Keys to exclude from masking (exact match) |
| Output | return | Dict[str, Any] |
New dictionary with sensitive values masked |
is_sensitive_key
| Direction | Name | Type | Description |
|---|---|---|---|
| Input | key | str |
Dictionary key to check |
| Input | excluded_keys | Optional[Set[str]] |
Keys to exclude from matching |
| Output | return | bool |
True if the key matches a sensitive pattern
|
Usage Examples
from litellm.litellm_core_utils.sensitive_data_masker import SensitiveDataMasker
masker = SensitiveDataMasker()
# Mask sensitive values in a config dictionary
data = {
"api_key": "sk-1234567890abcdef",
"redis_password": "very_secret_pass",
"port": 6379,
"tags": ["East US 2", "production"],
}
masked = masker.mask_dict(data)
# {
# "api_key": "sk-1****cdef",
# "redis_password": "very****pass",
# "port": 6379,
# "tags": ["East US 2", "production"],
# }
# Check if a key is sensitive
masker.is_sensitive_key("api_key") # True
masker.is_sensitive_key("max_tokens") # False (segment "tokens" != "token")
masker.is_sensitive_key("access_token") # True
# Exclude specific keys from masking
masked = masker.mask_dict(data, excluded_keys={"api_key"})
# api_key value remains unmasked
# Custom sensitive patterns and masking
custom_masker = SensitiveDataMasker(
sensitive_patterns={"ssn", "dob"},
visible_prefix=2,
visible_suffix=2,
mask_char="#",
)
Related Pages
- BerriAI_Litellm_App_Crypto -- encrypts sensitive data rather than masking it
- BerriAI_Litellm_Safe_JSON_Dumps -- safe serialization used alongside masking for logging