Some regular expressions here are vulnerable to ReDOS attack. Be sure to use them with following conditions:
- server side: Run these expression with libraries such as
google/re2,node-re2. - client side: avoid them, or at least impose necessary limitations on input.
npm install --save curegex
include curegex.js or curegex.tw.js, then use:
curegex.get("email").exec(mystring);
curegex.get("email", re2).exec(mystring); /* use `re2` regex engine instead of native RegExp */
set default regular expression engine:
curegex.engine(re2);
include curegex and use it by scope:
var curegex = require("curegex");
var curegextw = require("curegex").tw;
curegex.get(name, engine) accepts any RegExp-like constructor. Three engines are known to work:
curegex.get("email").exec(mystring);
fast and dependency-free, but vulnerable to ReDoS for some patterns. see Note above.
var re2 = require("re2");
curegex.tw.get("email", re2).exec(mystring);
linear-time matching ( ReDoS-safe ). note that re2 is a native module:
- it needs compilation toolchain / prebuilt binaries on install.
re2>= 1.26 requires Node^22.22.2 || ^24.15.0 || >=26.
var curegex = require("curegex");
var { RE2JS } = require("re2js");
curegex.tw.get("email", RE2JS).exec(mystring);
also linear-time ( ReDoS-safe ), no native compilation, works with any Node version and in browsers. curegex does not depend on re2js — install it yourself and pass the RE2JS class in; curegex detects it ( a class with static compile and flag constants, not a new-able RegExp-like constructor ) and wraps it into a RegExp-like engine automatically. the wrapper is also available explicitly:
var engine = curegex.adapters.re2js(RE2JS);
curegex.tw.get("email", engine).exec(mystring);
to switch between re2 and re2js, only the engine argument changes:
var engine = process.env.USE_RE2JS ? require("re2js").RE2JS : require("re2");
curegex.tw.get("email", engine).exec(mystring);
or set it once as default:
curegex.engine(engine); /* for curegex.get(...) */
curegex.tw.engine(engine); /* for curegex.tw.get(...) */
the effective engine is exposed as curegex.re ( and curegex.tw.re ) — always a new-able, RegExp-like constructor, so ad-hoc patterns can follow the same engine setting:
curegex.engine(RE2JS);
new curegex.re("^some-pattern$", "i").exec(mystring);
/* curegex.re is native RegExp when no engine is set */
password-len8-*rules use lookahead(?=...), which RE2-based engines ( bothre2andre2js) do not support —get()throws with these engines. use nativeRegExpfor them.- rules are maintained in engine-neutral syntax ( e.g., literal char ranges instead of
\uescapes, whichre2jsrejects ).npm testverifies every rule against all three engines. - the
re2jswrapper is RegExp-like, not a RegExp:exec()/test()work ( non-string input isString()-coerced like native RegExp ), but there is nosource/flags/lastIndex, and it cannot be passed toString.prototype.match/replace. - in
exec()results, unmatched capture groups arenullwithre2jsbutundefinedwithRegExp/re2( truthiness is the same ).
npm test
runs all rules against native RegExp, re2 and re2js, and checks the three engines agree.
- evil regex and rules of thumb: https://stackoverflow.com/questions/12841970/how-can-i-recognize-an-evil-regex
- per James Davis mentioned, avoid following:
- nesting quantifiers (
(a+)+) - quantified overlapping disjunctions (
(a|a)+) - quantified overlapping adjacencies (
\d+\d+)
- nesting quantifiers (
- visualize regular expression to spot above cases: https://regexper.com/
- per James Davis mentioned, avoid following:
- https://en.wikipedia.org/wiki/ReDoS
MIT