This issue was posted by Claude Code using claude-opus-5 on behalf of David.
Description
Patterns supplied via ScrubbingOptions.extra_patterns are compiled into the scrubbing regex and run over attribute values. MessageValueCleaner.clean_value is called during message formatting at span-creation time, so this runs on the application's own thread, not on the exporter thread.
A user pattern with nested quantifiers therefore turns an attribute value into a stall of the calling code:
import time, logfire
logfire.configure(
send_to_logfire=False,
scrubbing=logfire.ScrubbingOptions(extra_patterns=[r'(a+)+$']),
)
payload = 'a' * 26 + '!' # e.g. a field from an incoming request
t0 = time.perf_counter()
logfire.info('user said {msg}', msg=payload)
print(f'{(time.perf_counter() - t0) * 1000:.0f} ms')
Measured on logfire==4.40.0, Python 3.13.3, macOS:
| input length |
time |
| 16 |
13 ms |
| 20 |
183 ms |
| 24 |
3.0 s |
| 26 |
17.8 s |
27 (through logfire.info) |
28.3 s |
Growth is exponential, so a slightly longer value stalls the thread indefinitely.
The 18 entries in DEFAULT_PATTERNS are all linear and are not affected — the exposure comes only from user-supplied patterns. But the value being matched is frequently attacker-influenced (a request field, a header, a form value), so a well-meaning pattern turns instrumentation into a denial-of-service vector against the instrumented application itself.
Suggested fix
At minimum, document the risk on ScrubbingOptions.extra_patterns — nothing currently warns that user patterns run synchronously on the application thread against untrusted input.
Beyond that: rejecting obvious nested-quantifier shapes at configure time would catch the common cases cheaply. A full guarantee is not reachable with re.
Versions
logfire==4.40.0, Python 3.13.3, macOS.
Description
Patterns supplied via
ScrubbingOptions.extra_patternsare compiled into the scrubbing regex and run over attribute values.MessageValueCleaner.clean_valueis called during message formatting at span-creation time, so this runs on the application's own thread, not on the exporter thread.A user pattern with nested quantifiers therefore turns an attribute value into a stall of the calling code:
Measured on
logfire==4.40.0, Python 3.13.3, macOS:logfire.info)Growth is exponential, so a slightly longer value stalls the thread indefinitely.
The 18 entries in
DEFAULT_PATTERNSare all linear and are not affected — the exposure comes only from user-supplied patterns. But the value being matched is frequently attacker-influenced (a request field, a header, a form value), so a well-meaning pattern turns instrumentation into a denial-of-service vector against the instrumented application itself.Suggested fix
At minimum, document the risk on
ScrubbingOptions.extra_patterns— nothing currently warns that user patterns run synchronously on the application thread against untrusted input.Beyond that: rejecting obvious nested-quantifier shapes at configure time would catch the common cases cheaply. A full guarantee is not reachable with
re.Versions
logfire==4.40.0, Python 3.13.3, macOS.