diff --git a/packages/react-devtools-shared/src/__tests__/utils-test.js b/packages/react-devtools-shared/src/__tests__/utils-test.js index 9b9e82102cc..aedc8d2b1be 100644 --- a/packages/react-devtools-shared/src/__tests__/utils-test.js +++ b/packages/react-devtools-shared/src/__tests__/utils-test.js @@ -393,6 +393,24 @@ describe('utils', () => { 165558, ]); }); + + it('should handle malicious input without ReDoS vulnerability', () => { + // This test ensures the Firefox stack regex doesn't exhibit catastrophic + // backtracking (ReDoS) when processing malicious input patterns. + // See: https://github.com/facebook/react/issues/35490 + const nullChar = String.fromCharCode(0); + const maliciousInput = + ' ' + ('"' + nullChar).repeat(2000) + '\r!\r!' + '\n'; + + const startTime = Date.now(); + // This should complete quickly (< 100ms) instead of hanging for seconds + const result = extractLocationFromComponentStack(maliciousInput); + const elapsedTime = Date.now() - startTime; + + // The result should be null (no valid stack frame) and complete quickly + expect(result).toEqual(null); + expect(elapsedTime).toBeLessThan(100); + }); }); describe('symbolicateSource', () => { diff --git a/packages/react-devtools-shared/src/backend/utils/parseStackTrace.js b/packages/react-devtools-shared/src/backend/utils/parseStackTrace.js index e18c2d7baa1..35ed53631e8 100644 --- a/packages/react-devtools-shared/src/backend/utils/parseStackTrace.js +++ b/packages/react-devtools-shared/src/backend/utils/parseStackTrace.js @@ -59,7 +59,11 @@ function parseStackTraceFromChromeStack( return parsedFrames; } -const firefoxFrameRegExp = /^((?:.*".+")?[^@]*)@(.+):(\d+):(\d+)$/; +// Fix ReDoS vulnerability: Changed `.*".+"` to `"[^"]+"` to prevent catastrophic backtracking. +// The original pattern `(?:.*".+")?` with nested quantifiers could cause exponential time +// complexity on malicious inputs. Using `"[^"]+"` (negated character class) is O(n) and +// maintains the same matching behavior for valid Firefox stack frames. +const firefoxFrameRegExp = /^((?:"[^"]+")?[^@]*)@(.+):(\d+):(\d+)$/; function parseStackTraceFromFirefoxStack( stack: string, skipFrames: number,