This issue was posted by Grok Build using grok-4.6 on behalf of David.
Follow-up to #2190. The start-char prefilter is the right stdlib change. A DFA engine is still much faster on large attribute values.
Measurements
Median Pattern.search on Python 3.13, ~8k synthetic JSON attribute:
| engine |
benign |
matching |
stdlib re, no prefilter |
361µs |
362µs |
| #2190 1-char prefilter |
74µs |
75µs |
| 2-char / 3-char prefilter |
222–240µs |
slower than 1-char |
PyPI regex |
123µs |
123µs |
google-re2 (case-insensitive) |
5.7µs |
10.8µs |
google-re2 was about 13× faster than the prefiltered re on the benign 8k haystack, and about 15× on ~40k.
Why this is not a hard dependency
auth(?!ors?\b) does not compile. RE2 has no lookaround. See RE2 syntax and google-re2.
- Match objects are
re2._Match, not re.Match. ScrubMatch.pattern_match is part of the public callback API.
- Unicode case folding is not CPython
re.IGNORECASE. credentıal matches in re and misses in RE2. See re.IGNORECASE and re2#262.
- Latest
google-re2 wheels cover CPython 3.10–3.14 on macOS, manylinux, and Windows. There are no musllinux wheels. Alpine users would need a source build.
- User
extra_patterns are documented as ordinary re strings and may use lookaround.
PyPI regex is the wrong follow-up. It is still a backtracker, slower than the #2190 prefilter, and it also misses credentıal.
Suggested shape if we do this
Keep stdlib re as the default. Do not add google-re2 as a required dependency.
A later change could try google-re2 only for the default patterns, keep re for extra_patterns and for auth(?!ors?\b) (or a post-filter that preserves group(0) == 'auth'), and pick the leftmost match. Preserve ScrubMatch.pattern_match.group(0) / .span() for callbacks.
Sentry does not regex-scan values; it denylists keys. See Sentry scrubbing.
Follow-up to #2190. The start-char prefilter is the right stdlib change. A DFA engine is still much faster on large attribute values.
Measurements
Median
Pattern.searchon Python 3.13, ~8k synthetic JSON attribute:re, no prefilterregexgoogle-re2(case-insensitive)google-re2was about 13× faster than the prefilteredreon the benign 8k haystack, and about 15× on ~40k.Why this is not a hard dependency
auth(?!ors?\b)does not compile. RE2 has no lookaround. See RE2 syntax and google-re2.re2._Match, notre.Match.ScrubMatch.pattern_matchis part of the public callback API.re.IGNORECASE.credentıalmatches inreand misses in RE2. See re.IGNORECASE and re2#262.google-re2wheels cover CPython 3.10–3.14 on macOS, manylinux, and Windows. There are no musllinux wheels. Alpine users would need a source build.extra_patternsare documented as ordinaryrestrings and may use lookaround.PyPI
regexis the wrong follow-up. It is still a backtracker, slower than the #2190 prefilter, and it also missescredentıal.Suggested shape if we do this
Keep stdlib
reas the default. Do not addgoogle-re2as a required dependency.A later change could try
google-re2only for the default patterns, keepreforextra_patternsand forauth(?!ors?\b)(or a post-filter that preservesgroup(0) == 'auth'), and pick the leftmost match. PreserveScrubMatch.pattern_match.group(0)/.span()for callbacks.Sentry does not regex-scan values; it denylists keys. See Sentry scrubbing.