
Security News
Socket Releases Free Certified Patches for Nuxt Security Vulnerabilities
Socket releases free Certified Patches for high-severity Nuxt vulnerabilities, including server-side remote code execution through server island props.
This project provides Node.js bindings for RE2: a fast, safe alternative to backtracking regular expression engines written by Russ Cox in C++. To learn more about RE2, start with Regular Expression Matching in the Wild. More resources are on his Implementing Regular Expressions page.
RE2's regular expression language is almost a superset of what RegExp provides
(see Syntax),
but it lacks backreferences and lookahead assertions. See below for details.
RE2 always works in Unicode mode — character codes are interpreted as Unicode code points, not as binary values of UTF-16.
See RE2.unicodeWarningLevel below for details.
RE2 emulates standard RegExp, making it a practical drop-in replacement in most cases.
It also provides String-based regular expression methods. The constructor accepts RegExp directly, honoring all properties.
It can work with Node.js Buffers directly, reducing overhead and making processing of long files fast.
The project is a C++ addon built with nan. It cannot be used in web browsers. All documentation is in this README and in the wiki — browse the index, or search it by name.
The built-in Node.js regular expression engine can run in exponential time with a special combination:
This can lead to what is known as a Regular Expression Denial of Service (ReDoS). To check if your regular expressions are vulnerable, try one of these projects:
Neither project is perfect.
node-re2 protects against ReDoS by evaluating patterns in RE2 instead of the built-in regex engine.
To run the bundled benchmark (make sure node-re2 is built first):
npx nano-bench bench/bad-pattern.mjs
RE2 objects are created just like RegExp:
Supported flags: g (global), i (ignoreCase), m (multiline), s (dotAll), u (unicode, always on), y (sticky), d (hasIndices).
Supported properties:
re2.lastIndexre2.globalre2.ignoreCasere2.multilinere2.dotAllre2.unicode — always true; see details below.re2.stickyre2.hasIndicesre2.sourcere2.flagsSupported methods:
Well-known symbol-based methods are supported (see Symbols):
re2[Symbol.match](str)re2[Symbol.matchAll](str)re2[Symbol.search](str)re2[Symbol.replace](str, newSubStr|function)re2[Symbol.split](str[, limit])This lets you use RE2 instances on strings directly, just like RegExp:
const re = new RE2('1');
'213'.match(re); // [ '1', index: 1, input: '213' ]
'213'.search(re); // 1
'213'.replace(re, '+'); // 2+3
'213'.split(re); // [ '2', '3' ]
Array.from('2131'.matchAll(new RE2('1', 'g'))); // matchAll requires the g flag
// [['1', index: 1, input: '2131'], ['1', index: 3, input: '2131']]
Named groups are supported.
RE2 can be created from a regular expression:
const re1 = new RE2(/ab*/ig); // from a RegExp object
const re2 = new RE2(re1); // from another RE2 object
String methodsRE2 provides the standard String regex methods with swapped receiver and argument:
re2.match(str)
re2.replace(str, newSubStr|function)
re2.search(str)
re2.split(str[, limit])
These methods are also available as well-known symbol-based methods for transparent use with ES6 string/regex machinery.
Buffer supportMost methods accept Buffers instead of strings for direct UTF-8 processing:
re2.exec(buf)re2.test(buf)re2.match(buf)re2.search(buf)re2.split(buf[, limit])re2.replace(buf, replacer)Differences from string-based versions:
Buffer objects, even in composite objects. Convert with
buf.toString().When re2.replace() is used with a replacer function, the replacer receives string arguments and character offsets by default. Set useBuffers to true on the function to receive byte offsets instead:
function strReplacer(match, offset, input) {
// typeof match == "string"
return "<= " + offset + " characters|";
}
RE2("б").replace("абв", strReplacer);
// "а<= 1 characters|в"
function bufReplacer(match, offset, input) {
// typeof match == "string"
return "<= " + offset + " bytes|";
}
bufReplacer.useBuffers = true;
RE2("б").replace("абв", bufReplacer);
// "а<= 2 bytes|в"
This works for both string and buffer inputs. Buffer input produces buffer output; string input produces string output.
RE2.SetUse RE2.Set when the same string must be tested against many patterns. It builds a single automaton and frequently beats running individual regular expressions one by one.
While test() can be simulated by combining patterns with |, match() returns which patterns matched — something a single regular expression cannot do.
new RE2.Set(patterns[, flagsOrOptions][, options])
patterns is any iterable of strings, Buffers, RegExp, or RE2 instances; flags (if provided) apply to the whole set.flagsOrOptions can be a string/Buffer with standard flags (i, m, s, u, g, y, d).options.anchor can be 'unanchored' (default), 'start', or 'both'.options.maxMem is the DFA memory budget in bytes (positive integer). Default is 8 MiB — raise it to compile sets that would otherwise fail with "RE2.Set could not be compiled.".set.test(str) returns true if any pattern matches and false otherwise.set.match(str) returns an array of indexes of matching patterns.
set.size (number of patterns), set.flags (RegExp flags as a string), set.anchor (anchor mode as a string)set.source (all patterns joined with | as a string), set.sources (individual pattern sources as an array of strings)set.maxMem (number) — effective DFA memory budget in bytesIt is based on RE2::Set.
Example:
const routes = new RE2.Set([
'^/users/\\d+$',
'^/posts/\\d+$'
], 'i', {anchor: 'start'});
routes.test('/users/7'); // true
routes.match('/posts/42'); // [1]
routes.sources; // ['^/users/\\d+$', '^/posts/\\d+$']
routes.toString(); // '/^/users/\\d+$|^/posts/\\d+$/iu'
To run the bundled benchmark (make sure node-re2 is built first):
npx nano-bench bench/set-match.mjs
Two helpers convert between UTF-8 and UTF-16 sizes:
RE2.getUtf8Length(str) — byte size needed to encode a string as a UTF-8 buffer.RE2.getUtf16Length(buf) — character count needed to decode a UTF-8 buffer as a string.internalSourcesource emulates the standard RegExp property and can recreate an identical RE2 or RegExp instance. To inspect the RE2-translated pattern (useful for debugging), use the read-only internalSource property.
RE2 always works in Unicode mode. In most cases this is either invisible or preferred. For applications that need tight control, the static property RE2.unicodeWarningLevel governs what happens when a non-Unicode regular expression is created.
If a regular expression lacks the u flag, it is added silently by default:
const x = /./;
x.flags; // ''
const y = new RE2(x);
y.flags; // 'u'
Values of RE2.unicodeWarningLevel:
'nothing' (default) — silently add u.'warnOnce' — warn once, then silently add u. Assigning this value resets the one-time flag.'warn' — warn every time, still add u.'throw' — throw SyntaxError.Warnings and exceptions help audit an application for stray non-Unicode regular expressions.
RE2.unicodeWarningLevel is global. Be careful in multi-threaded environments — it is shared across threads.
npm install re2
The project works with other package managers but is not tested with them. See the wiki for notes on yarn and pnpm.
re2 supports every non-EOL Node.js release — current and active LTS lines. As a native (nan) addon it runs on Node.js only, not Bun or Deno. The authoritative supported range is the engines field in package.json; it also pins the minimum patch releases the build toolchain (node-gyp 13) requires. Check engines for the exact floor rather than a version repeated here.
re2 downloads or builds its native binary in an install script. Starting with npm 12
(July 2026), npm does not run dependency install scripts unless the package is listed in the
allowScripts field of your project's package.json — without it, npm install re2
fails with ESTRICTALLOWSCRIPTS. npm 11.16+ still runs the scripts but prints a warning.
Allow re2 before installing:
npm pkg set allowScripts.re2=true --json
npm install re2
Or use npm's approval tooling — note that npm approve-scripts only matches installed
packages, so under npm 12 the package has to be installed with scripts skipped first:
npm install re2 --ignore-scripts
npm approve-scripts re2
npm rebuild re2
npm approve-scripts pins the approval to the installed version, so version updates ask again;
pass --no-allow-scripts-pin (or use the allowScripts.re2=true form above) to allow all
versions. No other package in re2's dependency tree runs install scripts. For the full story see
NPM 12 and install scripts
and GitHub's official announcement of the npm v12 breaking changes.
The install script attempts to download a prebuilt artifact from GitHub Releases. A download from GitHub is verified against the SHA-256 hashes pinned in this package's artifactHashes field before it is used — a binary that is not byte-for-byte the one published is rejected. Override the download location with the RE2_DOWNLOAD_MIRROR environment variable (a mirror serves your own builds and is not hash-checked). To skip the download entirely and always build from source, set RE2_DOWNLOAD_FORCE_BUILD to a non-empty value.
If the download fails or is rejected, the script builds RE2 locally using node-gyp.
It is used just like RegExp.
const RE2 = require('re2');
// with default flags
let re = new RE2('a(b*)');
let result = re.exec('abbc');
console.log(result[0]); // 'abb'
console.log(result[1]); // 'bb'
result = re.exec('aBbC');
console.log(result[0]); // 'a'
console.log(result[1]); // ''
// with explicit flags
re = new RE2('a(b*)', 'i');
result = re.exec('aBbC');
console.log(result[0]); // 'aBb'
console.log(result[1]); // 'Bb'
// from regular expression object
const regexp = new RegExp('a(b*)', 'i');
re = new RE2(regexp);
result = re.exec('aBbC');
console.log(result[0]); // 'aBb'
console.log(result[1]); // 'Bb'
// from regular expression literal
re = new RE2(/a(b*)/i);
result = re.exec('aBbC');
console.log(result[0]); // 'aBb'
console.log(result[1]); // 'Bb'
// from another RE2 object
const rex = new RE2(re);
result = rex.exec('aBbC');
console.log(result[0]); // 'aBb'
console.log(result[1]); // 'Bb'
// shortcut
result = new RE2('ab*').exec('abba');
// factory
result = RE2('ab*').exec('abba');
RE2 avoids any regular expression features that require worst-case exponential time to evaluate.
The most notable missing features are backreferences and lookahead assertions.
If your application uses them, you should continue to use RegExp —
but since they are fundamentally vulnerable to
ReDoS,
consider replacing them.
RE2 throws SyntaxError for unsupported features.
Wrap RE2 declarations in a try-catch to fall back to RegExp:
let re = /(a)+(b)*/;
try {
re = new RE2(re);
// use RE2 as a drop-in replacement
} catch (e) {
// use the original RegExp
}
const result = re.exec(sample);
RE2 may also behave differently from the built-in engine in corner cases.
RE2 does not support backreferences — numbered references to previously
matched groups (\1, \2, etc.). Example:
/(cat|dog)\1/.test("catcat"); // true
/(cat|dog)\1/.test("dogdog"); // true
/(cat|dog)\1/.test("catdog"); // false
/(cat|dog)\1/.test("dogcat"); // false
RE2 does not support lookahead assertions, which make a match depend on subsequent contents.
/abc(?=def)/; // match abc only if it is followed by def
/abc(?!def)/; // match abc only if it is not followed by def
RE2 and the built-in engine may disagree in edge cases. Verify your regular expressions before switching. They should work in the vast majority of cases.
Example:
const RE2 = require('re2');
const pattern = '(?:(a)|(b)|(c))+';
const built_in = new RegExp(pattern);
const re2 = new RE2(pattern);
const input = 'abc';
const bi_res = built_in.exec(input);
const re2_res = re2.exec(input);
console.log('bi_res: ' + bi_res); // prints: bi_res: abc,,,c
console.log('re2_res : ' + re2_res); // prints: re2_res : abc,a,b,c
RE2 always works in Unicode mode. See RE2.unicodeWarningLevel above for details.
\p{...} and \P{...}node-re2 follows MDN's Unicode character class escape reference — the same set of property escapes that JavaScript's native RegExp accepts with the u flag.
Supported categories:
General_Category — both short names (e.g., \p{L}, \p{Lu}) and long names (e.g., \p{Letter}, \p{Uppercase_Letter}). The gc= and General_Category= prefixes also work: \p{gc=Letter}, \p{General_Category=Letter}.
Script — e.g., \p{Script=Latin}, \p{sc=Cyrillic}. ISO 15924 four-letter codes are accepted as well: \p{sc=Latn}.
Script_Extensions — e.g., \p{Script_Extensions=Hani}, \p{scx=Latn}. Matches characters whose Script_Extensions list includes the named script (a superset of Script=).
Binary properties — the full ECMAScript set of binary properties, including:
Alphabetic, ASCII, ASCII_Hex_Digit, Hex_Digit, White_Space, Math, Dash, Diacritic, Quotation_Mark, Bidi_Mirrored, Bidi_Control, Default_Ignorable_Code_PointLowercase, Uppercase, Cased, Case_Ignorable, Changes_When_Lowercased, Changes_When_Uppercased, Changes_When_Casefolded, Changes_When_Casemapped, Changes_When_Titlecased, Changes_When_NFKC_CasefoldedID_Start, ID_Continue, XID_Start, XID_Continue, Pattern_Syntax, Pattern_White_SpaceEmoji, Emoji_Presentation, Emoji_Modifier, Emoji_Modifier_Base, Emoji_Component, Extended_Pictographic, Regional_IndicatorGrapheme_Base, Grapheme_Extend, Extender, Variation_Selector, Join_Control, Logical_Order_Exception, Sentence_Terminal, Terminal_Punctuation, Soft_Dotted, Radical, Unified_Ideograph, Ideographic, IDS_Binary_Operator, IDS_Trinary_Operator, Noncharacter_Code_Point, Deprecated, Any, AssignedShort aliases listed in PropertyAliases.txt are accepted alongside the canonical names: \p{Alpha} ≡ \p{Alphabetic}, \p{Hex} ≡ \p{Hex_Digit}, \p{Lower} ≡ \p{Lowercase}, etc.
The negated form \P{...} and use inside character classes ([\p{L}\p{Emoji}], [^\p{ASCII}]) work for every category.
Not supported: Properties of Strings (\p{Basic_Emoji}, \p{RGI_Emoji}, etc.). These match multi-codepoint sequences and require the v flag, which RE2 does not model.
Tables are baked in at build time from Unicode 17.0. To target a newer Unicode version, bump @unicode/unicode-XX.X.X in devDependencies and run node scripts/gen-unicode-properties.mjs.
match() with an empty-matchable pattern (a*, (?:), …) no longer loops forever exhausting memory (GHSA-6hxr-mr5r-9836), and an out-of-range lastIndex on a non-ASCII subject no longer reads past the buffer and crashes (GHSA-ff84-5f28-78qj). Both now match the built-in engine. Thx, ataberk-xyz.replace() using an output-amplifying template ($' or $`) on very large input could exceed V8's maximum string length and abort the whole process. It now throws a catchable RangeError, matching the built-in engine. Thx, ataberk-xyz.maxMem option for RE2.Set. Faster matching on pure-ASCII inputs. Narrowed Node support — drops Node 25.x and older patch releases.import {RE2} from 're2'. Added CJS test. Updated docs and dependencies.RE2.Set (thx, Wes).exec() index (reported by matthewvalentine, thx) and match() index.npm corepack problem (thx, Steven).absail-cpp files that manifested itself on NixOS. Thx, Laura Hausmann.install-artifact-from-github. A default HTTPS agent is used for fetching precompiled artifacts avoiding unnecessary long wait times.absail-cpp files that manifested itself on ARM Alpine. Thx, Laura Hausmann.node-gyp.abseil-cpp and required the adaptation work. Thx, Stefano Rivera.The rest can be consulted in the project's wiki Release history.
BSD-3-Clause
The 'regexp' package provides a simple interface for working with regular expressions in JavaScript. It is similar to re2 but does not offer the same level of performance and safety guarantees against catastrophic backtracking.
The 'xregexp' package extends JavaScript's native RegExp with additional features and syntax. It offers more functionality than re2 but may not be as performant or safe in terms of avoiding catastrophic backtracking.
The 'pcre-to-regexp' package allows you to convert Perl-compatible regular expressions (PCRE) to JavaScript RegExp objects. While it provides compatibility with PCRE syntax, it does not offer the same performance and safety benefits as re2.
FAQs
Bindings for RE2: fast, safe alternative to backtracking regular expression engines.
The npm package re2 receives a total of 2,314,476 weekly downloads. As such, re2 popularity was classified as popular.
We found that re2 demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Security News
Socket releases free Certified Patches for high-severity Nuxt vulnerabilities, including server-side remote code execution through server island props.

Security News
An open letter signed by 50 companies, from NVIDIA and Microsoft to Mistral and Hugging Face, urges Washington not to restrict open weight AI.

Security News
/Research
A fake corepack.org site is impersonating the Node.js tool and delivers an infostealer and proxyware to developers who download it.