Build1 distinct publisher3 min readPublished Updated
A dev.to writeup treats regex safety as a measurement problem rather than a blacklist of bad shapes, and the acceptance criterion for a rewrite is the shape of the curve on the same hostile input. The author warns the absolute milliseconds move with hardware and engine version.
The Engineer · Build desk

Compiled by The EngineerSomething wrong?How this is made
Backtracking is what turns a two-character difference into a factor of four. Most JavaScript regexes backtrack: the engine takes a greedy path, then revisits earlier choices when something downstream fails [4]. In `/^(a+)+$/` the inner quantifier can consume one `a` or many and the outer one can repeat the group, so a run of `a` characters can be split many ways, and appending one character that cannot match means the engine has to explore that growing set of partitions before it can return `false` [6].
Compound the recorded factor across the tested range. The harness walks 20 to 30 in steps of two [9], which is five steps, and roughly four per step [10] puts the run at length 30 at about 1,024 times the work of the run at length 20 [11]. The curve is the part the author says survives a change of machine; absolute timings move with hardware and engine version [3].
For the number to mean anything on your box, you need a backtracking engine [4], input you do not bound [18], and an anchor or required literal sitting after the ambiguous part so a failure is forced [17]. That last condition is why the checklist lists it separately from nesting [17]. Nesting is a review signal, not a proof of exploitation [13]. The harder family does not look nested at all: `/^(a|aa)+$/` lets either branch consume the next characters, and in production patterns the overlap hides inside classes such as `\w|\d`, where every digit satisfies both branches [14]. Grepping for a quantifier wrapped in a quantifier finds `(\d+)*` and walks straight past that [13][14].
Measuring is not free either. The author will not run an unknown pattern against unbounded input on a production request thread, and puts short controlled samples in an isolated test process or worker, stopping before the duration becomes disruptive [12]. That means this audit is not a lint rule. It is a harness you can kill.
The repair in the minimal case is deletion: `/^a+$/` accepts one or more `a` and rejects everything else, exactly as the nested version did, with the ambiguity gone [15]. Most ambiguity is less considerate about where it hides.
What I would actually adopt is the acceptance criterion. The author declines to treat the recorded milliseconds as a universal benchmark and instead requires the change in growth behaviour, with the repaired pattern staying approximately linear on the same family of inputs [16]. That is a stricter bar than one fast run, and it is testable in CI against the same six lengths [9][16]. Keep the length bound after the rewrite as well: OWASP's input-validation guidance asks for explicit minimum and maximum lengths, and those bounds cap the damage from whatever got through review [18].
Ranked by verification strength, evidence, and original report placement.
The exact timings come from a Node.js 22 test run used for the original CodeSwap guide; the author states that hardware and engine versions change absolute numbers but the growth curve is the useful signal.
On the recorded run, every two added characters multiplied the time by roughly four, and the author treats accelerating growth rather than a single slow result as the evidence.
The author maintains CodeSwap, a developer-tools site with browser-based utilities and technical guides, and began the work while reviewing its regular-expression tools.
The author's answer was not another list of patterns labeled safe or unsafe but a small audit process: identify ambiguous repetition, construct a failing input, measure growth at several lengths, rewrite the pattern, and measure the same input again.
Most JavaScript regular expressions use backtracking: the engine makes a greedy choice, and if something later fails it revisits earlier choices.
Backtracking is normally harmless; the dangerous case appears when the same characters can be divided or matched in many different ways.
Distinct publishers with included, body-backed reporting in this cluster.
dev.to
1 article · August 29, 2026
Follow any of these and your For You feed starts watching them — no settings page required.
build
The ICO fines what you cannot prove: Article 32 makes encryption and erasure an engineering liability1 distinct publisher
build
Allow-list the closed set, block-list the open one: 193 thin geo pages, one gate1 distinct publisher
build
A GAN beauty filter is a device budget allocation, not a feature toggle1 distinct publisher
build
Every viewer hits your HLS key endpoint in the same second, and almost nobody tests it1 distinct publisher
Evidence-backed comparisons of source perspectives and observed adoption signals. Read the methodology
Which Builder, Operator, and Investor concerns the observed source mix emphasized—not a truth score.
Evidence, demonstrated adoption, hype gap, incentives, and confidence are assessed independently, each on its own current evidence. How these are measured.
Standard mechanism, one unshown run
The mechanism is not in dispute — nested repetition plus a forced failure is the canonical catastrophic-backtracking shape, and the author's reading of OWASP's warning signs matches it. The soft spot is the number readers will repeat: a fourfold jump per two characters is asserted but the timing table it came from is never printed, and that table is a single Node.js 22 run on unnamed hardware, recorded for the author's own guide. Everything structural here you can check; everything numeric you have to take on trust or rerun yourself.
No usage signal of any kind
Nothing in this reporting says whether anyone other than the author has run the audit or the checker. There are no downloads, no dependents, no bug reports, no CI integration, and no incident in which the method caught something — just a workflow described by the person who built the tool around it.
Quieter than its own headline
The restraint is real and worth noting: the author refuses to treat his milliseconds as a benchmark, says nesting proves nothing on its own, admits a single timing sample can miss an engine-specific worst case, and calls his checker a review aid rather than a certification. Set against that, the trailing '!' framing in our own headline is louder than anything he actually claims. The overreach risk sits not in the argument but in the missing table, which invites readers to quote a curve they were never shown.
Disclosed funnel to the author's own tool
The disclosure is printed rather than uncovered: the author maintains CodeSwap, every link points there, the canonical version lives on that domain, and the full measurement table stays behind on the site instead of travelling into the dev.to copy. He also says this writeup was prepared with AI assistance from the site's implementation and test records. None of that makes the backtracking argument wrong, but it does mean the one party attesting to the numbers is the one whose traffic those numbers serve.
Cheap to falsify, never yet checked
Two forces pull opposite ways. On one side, a lone self-published account with a commercial interest and no outside verification. On the other, a claim so cheap to test that scepticism costs a minute at a terminal, resting on engine behaviour that has been documented for years. We would repeat the shape of the curve without hesitation and would not repeat the milliseconds.