Complex regex with overlapping alternation causes catastrophic backtracking — blocks the event loop.
Catastrophic backtracking happens when a regex has overlapping alternation or nested repetition. The engine tries exponentially many combinations before giving up, blocking the event loop. A single request can take 30+ seconds. Even well-known packages (cross-spawn, path-to-regexp, fast-xml-parser) have shipped ReDoS CVEs that were discovered post-release.
// VULNERABLE — catastrophic backtracking const emailRegex = /^([a-zA-Z0-9])+([a-zA-Z0-9._-])*@([a-zA-Z0-9-])+(\/[a-zA-Z0-9-._~:?#[\\]!$&'()*+,;=]*)*$/; // Attacker: aaaaaaaaaaaaaaaaaaaaaaaa!
// FIXED — atomic groups / possessive quantifiers, or use a non-backtracking engine
// Option 1: split into simpler checks
const isValidEmail = (email) => {
const [local, domain] = email.split('@');
if (!local || !domain) return false;
if (!/^[a-zA-Z0-9.-]+$/.test(local)) return false;
if (!/^[a-zA-Z0-9.-]+$/.test(domain)) return false;
return true;
};
// Option 2: use re2 (non-backtracking)
// const RE2 = require('re2');
// const safeRegex = new RE2(pattern);
pool.query(`SELECT * FROM users WHERE id = ${req.params.id}`)