Skip to content

fix(tracer): prevent catastrophic backtracking in query string obfuscation on multibyte URL-encoded filenames#8847

Open
kisungyi92 wants to merge 1 commit into
DataDog:masterfrom
kisungyi92:fix/query-string-obfuscation-backtracking-multibyte
Open

fix(tracer): prevent catastrophic backtracking in query string obfuscation on multibyte URL-encoded filenames#8847
kisungyi92 wants to merge 1 commit into
DataDog:masterfrom
kisungyi92:fix/query-string-obfuscation-backtracking-multibyte

Conversation

@kisungyi92

Copy link
Copy Markdown

Summary

URL-encoded multibyte filenames (Korean/Japanese/CJK) in query string parameters trigger catastrophic backtracking in the default DD_TRACE_OBFUSCATION_QUERY_STRING_REGEXP when combined with auth-related parameters (e.g. a Vault ticket parameter).

In production this caused RegexInterpreter.Go() to consume 16.34s/min (vs 3ms baseline), and system.cpu.user to spike from ~1.6% to 90% with zero application code changes after APM instrumentation.

Datadog Continuous Profiler confirmed the root cause via A/B comparison: TrackPush, StackPush, and Goto (backtracking-only methods) were completely absent before instrumentation and spiked immediately after.

Root Cause

The three backtracking-prone patterns in the default regex fire simultaneously on Vault file download URLs containing URL-encoded Korean filenames:

  • (?:%2[^2]|%[^2]|[^"%])+ — 70+ %XX bytes accumulate before failing to find closing ", then full rollback
  • ey[I-L](?:[\w=-]|%3D)+\.ey[I-L]... — greedily matches filename chars, fails on required . separator
  • (?:[a-z0-9/.+]|%2F|%5C|%2B){100,} — 100+ iterations across %2F-containing encoded content

Example triggering URL:

/Vault/vaultserver.aspx
  ?fileName=%EC%84%A4%EA%B3%84%EC%9E%90%EB%A3%8C_.xlsx
  &vaultId=67BBB9204FE84A8981ED8313049BA06C
  &ticket=VAULT_TOKEN

Changes

Obfuscator.cs — two complementary fixes:

  1. Pre-strip high-byte URL-encoded sequences (%80–%FF) before running the obfuscation regex. Credential patterns (tokens, keys, passwords) are ASCII-only; multibyte-encoded characters cannot contain sensitive data, so stripping them removes the backtracking trigger while keeping all ASCII parameters intact.

  2. RegexOptions.NonBacktracking on .NET 7+ — guarantees O(n) matching time regardless of input, as defense-in-depth.

QueryStringObfuscatorTests.cs — regression tests:

  • Korean/Japanese filename + token parameter (exact production trigger)
  • ASCII-only URLs (no regression in existing behavior)
  • Performance assertion: completes within 1s on long encoded filenames

Test Plan

  • QueryStringObfuscatorTests.ObfuscateWithDefaultPattern_MultibyteUrlEncoding — correctness
  • QueryStringObfuscatorTests.ObfuscateWithDefaultPattern_MultibyteUrlEncoding_CompletesWithinTimeout — performance regression guard
  • All existing ObfuscateWithDefaultPattern tests still pass

Affected Customers

Any customer where HTTP request URLs contain URL-encoded multibyte characters and a parameter name matching the default regex keyword list (token, auth, sign, secret, key, password, etc.). Particularly likely in Korean/Japanese/Chinese deployments, document management systems, and file servers.

…ation on multibyte URL-encoded filenames

Multibyte (Korean/CJK) filenames URL-encoded in query string parameters
(%EC%84%A4... sequences) trigger catastrophic backtracking in the default
DD_TRACE_OBFUSCATION_QUERY_STRING_REGEXP when combined with auth-related
parameters (e.g. Vault ticket). The three problematic patterns are:

1. (?:%2[^2]|%[^2]|[^"%])+ — JSON key:value alternation
2. ey[I-L](?:[\w=-]|%3D)+ — JWT header match
3. (?:[a-z0-9/.+]|%2F|%5C|%2B){100,} — SSH key match

In production, this caused RegexInterpreter.Go() to consume 16.34s/min
(vs. 3ms baseline) and system.cpu.user to spike from 1.6% to 90%.

Two complementary fixes are applied:

1. Pre-strip high-byte URL-encoded sequences (%80–%FF) before running the
   obfuscation regex. Credential patterns are ASCII-only, so these sequences
   cannot contain sensitive data and stripping them removes the backtracking
   trigger entirely while keeping all ASCII parameters intact.

2. Use RegexOptions.NonBacktracking on .NET 7+ to guarantee O(n) matching
   time regardless of input, as a defense-in-depth measure.

Adds regression tests covering:
- Korean/Japanese filename + token parameter (the exact production trigger)
- ASCII-only URLs to verify no regression in existing behavior
- Performance test asserting completion within 1s on long encoded filenames
@kisungyi92 kisungyi92 requested a review from a team as a code owner June 29, 2026 13:57
@andrewlock

Copy link
Copy Markdown
Member

Hi @kisungyi92, thanks for raising this, and sorry to hear you ran into issues. Unfortunately, the .NET tracer does not directly target .NET 7+ (for various reasons) so this code won't work as you expect. As for the assertion that "Credential patterns (tokens, keys, passwords) are ASCII-only", I'm not sure whether that's something we can completely assert 🤔

Either way, we'll look into the issue and get back to you, thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants