|
23 | 23 | """ |
24 | 24 |
|
25 | 25 | import warnings |
26 | | -from typing import TYPE_CHECKING, cast |
| 26 | +from typing import TYPE_CHECKING, List, Mapping, Optional, cast |
| 27 | + |
| 28 | +from sentry_sdk._types import SENSITIVE_DATA_SUBSTITUTE |
27 | 29 |
|
28 | 30 | if TYPE_CHECKING: |
29 | 31 | from typing import Any, Dict, Literal |
|
77 | 79 | ] |
78 | 80 |
|
79 | 81 |
|
| 82 | +def _is_sensitive_key(key: str, extra_terms: "Optional[List[str]]" = None) -> bool: |
| 83 | + """ |
| 84 | + Return whether ``key`` matches the sensitive denylist using a partial, |
| 85 | + case-insensitive substring match. |
| 86 | +
|
| 87 | + :param extra_terms: additional deny terms (e.g. user-provided) to consider |
| 88 | + alongside the built-in `_SENSITIVE_DENYLIST`. |
| 89 | + """ |
| 90 | + lowered = key.lower() |
| 91 | + for term in _SENSITIVE_DENYLIST: |
| 92 | + if term in lowered: |
| 93 | + return True |
| 94 | + if extra_terms: |
| 95 | + for term in extra_terms: |
| 96 | + if term and term.lower() in lowered: |
| 97 | + return True |
| 98 | + return False |
| 99 | + |
| 100 | + |
| 101 | +def _apply_key_value_collection_filtering( |
| 102 | + items: "Mapping[str, Any]", |
| 103 | + behaviour: "KeyValueCollectionBehaviour", |
| 104 | + substitute: "Any" = SENSITIVE_DATA_SUBSTITUTE, |
| 105 | +) -> "Dict[str, Any]": |
| 106 | + |
| 107 | + if behaviour["mode"] == "off": |
| 108 | + return {} |
| 109 | + |
| 110 | + result: "Dict[str, Any]" = {} |
| 111 | + |
| 112 | + if behaviour["mode"] == "allowlist": |
| 113 | + for key, value in items.items(): |
| 114 | + is_allowed = False |
| 115 | + if isinstance(key, str): |
| 116 | + lowered = key.lower() |
| 117 | + is_allowed = any( |
| 118 | + term and term.lower() in lowered |
| 119 | + for term in behaviour.get("terms", []) |
| 120 | + ) |
| 121 | + if is_allowed and not _is_sensitive_key(key): |
| 122 | + result[key] = value |
| 123 | + else: |
| 124 | + result[key] = substitute |
| 125 | + return result |
| 126 | + |
| 127 | + # denylist behaviour |
| 128 | + for key, value in items.items(): |
| 129 | + if isinstance(key, str) and _is_sensitive_key( |
| 130 | + key=key, extra_terms=behaviour.get("terms", []) |
| 131 | + ): |
| 132 | + result[key] = substitute |
| 133 | + else: |
| 134 | + result[key] = value |
| 135 | + return result |
| 136 | + |
| 137 | + |
80 | 138 | def _map_from_send_default_pii( |
81 | 139 | *, |
82 | 140 | send_default_pii: bool, |
|
0 commit comments