fix(tracer): prevent catastrophic backtracking in query string obfuscation on multibyte URL-encoded filenames#8847
Open
kisungyi92 wants to merge 1 commit into
Conversation
…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
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! |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
URL-encoded multibyte filenames (Korean/Japanese/CJK) in query string parameters trigger catastrophic backtracking in the default
DD_TRACE_OBFUSCATION_QUERY_STRING_REGEXPwhen combined with auth-related parameters (e.g. a Vaultticketparameter).In production this caused
RegexInterpreter.Go()to consume 16.34s/min (vs 3ms baseline), andsystem.cpu.userto 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, andGoto(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+%XXbytes accumulate before failing to find closing", then full rollbackey[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 contentExample triggering URL:
Changes
Obfuscator.cs— two complementary fixes: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.RegexOptions.NonBacktrackingon .NET 7+ — guarantees O(n) matching time regardless of input, as defense-in-depth.QueryStringObfuscatorTests.cs— regression tests:Test Plan
QueryStringObfuscatorTests.ObfuscateWithDefaultPattern_MultibyteUrlEncoding— correctnessQueryStringObfuscatorTests.ObfuscateWithDefaultPattern_MultibyteUrlEncoding_CompletesWithinTimeout— performance regression guardObfuscateWithDefaultPatterntests still passAffected 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.