diff --git a/presidio-analyzer/presidio_analyzer/predefined_recognizers/country_specific/us/us_ssn_recognizer.py b/presidio-analyzer/presidio_analyzer/predefined_recognizers/country_specific/us/us_ssn_recognizer.py index aec146f1d..c3e60f76c 100644 --- a/presidio-analyzer/presidio_analyzer/predefined_recognizers/country_specific/us/us_ssn_recognizer.py +++ b/presidio-analyzer/presidio_analyzer/predefined_recognizers/country_specific/us/us_ssn_recognizer.py @@ -77,8 +77,12 @@ def invalidate_result(self, pattern_text: str) -> bool: # groups cannot be all zeros return True - for sample_ssn in ("000", "666", "123456789", "98765432", "078051120"): - if only_digits.startswith(sample_ssn): - return True + if only_digits[:3] in ("000", "666"): + # area number (first group) is never issued by the SSA + return True + + if only_digits in ("123456789", "987654320", "078051120"): + # canonical sample/placeholder SSNs published for examples + return True return False diff --git a/presidio-analyzer/tests/test_us_ssn_recognizer.py b/presidio-analyzer/tests/test_us_ssn_recognizer.py index b7b2aa0bf..c0900b475 100644 --- a/presidio-analyzer/tests/test_us_ssn_recognizer.py +++ b/presidio-analyzer/tests/test_us_ssn_recognizer.py @@ -27,6 +27,20 @@ def entities(): ("078.05.1123", 1, ((0, 11),), ((0.5, 0.6),),), ("078 05 1123", 1, ((0, 11),), ((0.5, 0.6),),), ("abc 078 05 1123 abc", 1, ((4, 15),), ((0.5, 0.6),),), + # The truncated "98765432" sample literal must not prefix-block the + # neighbouring 987-65-432X family; only the canonical 987-65-4320 sample + # is invalidated (by exact match), the rest are real SSN-shaped values + ("987-65-4321", 1, ((0, 11),), ((0.5, 0.6),),), + ("987-65-4322", 1, ((0, 11),), ((0.5, 0.6),),), + ("987-65-4323", 1, ((0, 11),), ((0.5, 0.6),),), + ("987-65-4324", 1, ((0, 11),), ((0.5, 0.6),),), + ("987-65-4325", 1, ((0, 11),), ((0.5, 0.6),),), + ("987-65-4326", 1, ((0, 11),), ((0.5, 0.6),),), + ("987-65-4327", 1, ((0, 11),), ((0.5, 0.6),),), + ("987-65-4328", 1, ((0, 11),), ((0.5, 0.6),),), + ("987-65-4329", 1, ((0, 11),), ((0.5, 0.6),),), + # a normal valid SSN is still detected + ("219-09-9999", 1, ((0, 11),), ((0.5, 0.6),),), # no match ("0780511201", 0, (), (),), ("078051120", 0, (), (),), @@ -35,6 +49,13 @@ def entities(): ("078-05-0000", 0, (), (),), ("078 00 1123", 0, (), (),), ("693-09.4444", 0, (), (),), + # canonical sample SSNs stay invalidated (now via exact match) + ("987-65-4320", 0, (), (),), + ("078-05-1120", 0, (), (),), + ("123-45-6789", 0, (), (),), + # never-issued area numbers (000/666) stay invalidated via the area check + ("000-12-3456", 0, (), (),), + ("666-12-3456", 0, (), (),), # fmt: on ], )