Skip to content

Commit 499194e

Browse files
feat: limit max number of items in collection to scan (#430)
* feat: limit max number of items in collection to scan * feat: changelog * fix: format * feat: test * feat: replace entire collection instead of truncating
1 parent ffb8e9b commit 499194e

4 files changed

Lines changed: 58 additions & 1 deletion

File tree

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
# 7.8.6 - 2026-02-09
2+
3+
fix: limit collections scanning in code variables
4+
15
# 7.8.5 - 2026-02-09
26

37
fix: further optimize code variables pattern matching

posthog/exception_utils.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@
6666
CODE_VARIABLES_TOO_LONG_VALUE = "$$_posthog_value_too_long_$$"
6767

6868
_MAX_VALUE_LENGTH_FOR_PATTERN_MATCH = 5_000
69+
_MAX_COLLECTION_ITEMS_TO_SCAN = 100
6970
_REGEX_METACHARACTERS = frozenset(r"\.^$*+?{}[]|()")
7071

7172
DEFAULT_TOTAL_VARIABLES_SIZE_LIMIT = 20 * 1024
@@ -991,6 +992,8 @@ def _mask_sensitive_data(value, compiled_mask, _seen=None):
991992
_seen.add(obj_id)
992993

993994
if isinstance(value, dict):
995+
if len(value) > _MAX_COLLECTION_ITEMS_TO_SCAN:
996+
return CODE_VARIABLES_TOO_LONG_VALUE
994997
result = {}
995998
for k, v in value.items():
996999
key_str = str(k) if not isinstance(k, str) else k
@@ -1002,6 +1005,8 @@ def _mask_sensitive_data(value, compiled_mask, _seen=None):
10021005
result[k] = _mask_sensitive_data(v, compiled_mask, _seen)
10031006
return result
10041007
elif isinstance(value, (list, tuple)):
1008+
if len(value) > _MAX_COLLECTION_ITEMS_TO_SCAN:
1009+
return CODE_VARIABLES_TOO_LONG_VALUE
10051010
masked_items = [
10061011
_mask_sensitive_data(item, compiled_mask, _seen) for item in value
10071012
]

posthog/test/test_exception_capture.py

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -639,3 +639,51 @@ def test_compile_patterns_fast_path_and_regex_fallback():
639639

640640
# No match
641641
assert _pattern_matches("safe_var", mixed) is False
642+
643+
644+
def test_mask_sensitive_data_large_dict_replaced():
645+
from posthog.exception_utils import (
646+
CODE_VARIABLES_TOO_LONG_VALUE,
647+
_compile_patterns,
648+
_mask_sensitive_data,
649+
)
650+
651+
compiled_mask = _compile_patterns([r"(?i)password"])
652+
653+
large_dict = {f"key_{i}": f"value_{i}" for i in range(300)}
654+
655+
result = _mask_sensitive_data(large_dict, compiled_mask)
656+
657+
assert result == CODE_VARIABLES_TOO_LONG_VALUE
658+
659+
660+
def test_mask_sensitive_data_large_list_replaced():
661+
from posthog.exception_utils import (
662+
CODE_VARIABLES_TOO_LONG_VALUE,
663+
_compile_patterns,
664+
_mask_sensitive_data,
665+
)
666+
667+
compiled_mask = _compile_patterns([r"(?i)password"])
668+
669+
large_list = [f"item_{i}" for i in range(300)]
670+
671+
result = _mask_sensitive_data(large_list, compiled_mask)
672+
673+
assert result == CODE_VARIABLES_TOO_LONG_VALUE
674+
675+
676+
def test_mask_sensitive_data_large_tuple_replaced():
677+
from posthog.exception_utils import (
678+
CODE_VARIABLES_TOO_LONG_VALUE,
679+
_compile_patterns,
680+
_mask_sensitive_data,
681+
)
682+
683+
compiled_mask = _compile_patterns([r"(?i)password"])
684+
685+
large_tuple = tuple(f"item_{i}" for i in range(300))
686+
687+
result = _mask_sensitive_data(large_tuple, compiled_mask)
688+
689+
assert result == CODE_VARIABLES_TOO_LONG_VALUE

posthog/version.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
VERSION = "7.8.5"
1+
VERSION = "7.8.6"
22

33
if __name__ == "__main__":
44
print(VERSION, end="") # noqa: T201

0 commit comments

Comments
 (0)