{"id":"GHSA-6hxr-mr5r-9836","revision":null,"records":[{"revision":"f81784908f224b6e98eafa1b267022b9","observedAt":"2026-10-23T15:48:27.903+00:00","statement":{"source":"cve-program","id":"CVE-2026-68499","aliases":[],"title":"re2: Global `String.prototype.match` with an empty-matchable pattern never advances → infinite loop with unbounded native memory growth (DoS)","description":"re2 provides Node.js bindings for Google's RE2 regular expression engine. Prior to 1.25.2, re2's String.prototype.match implementation with a global RE2 pattern that can match the empty string fails to advance its native matching cursor in lib/match.cc, causing an infinite loop and unbounded native memory growth that blocks the event loop and can exhaust host memory. This issue is fixed in 1.25.2.","state":0,"publishedAt":"2026-07-30T20:07:01.147+00:00","modifiedAt":"2026-07-31T19:19:08.646+00:00","affected":[{"ecosystem":"Vendor product","name":"node-re2","ranges":[],"versions":[],"rawVersionEvidence":"{\n                    \"vendor\": \"uhop\",\n                    \"product\": \"node-re2\",\n                    \"versions\": [\n                        {\n                            \"version\": \"< 1.25.2\",\n                            \"status\": \"affected\"\n                        }\n                    ]\n                }"}],"metrics":[{"system":"CVSS 3.1","vector":"CVSS:3.1/AV:L/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H","score":6.2,"severity":"MEDIUM"}],"references":["https://github.com/uhop/node-re2/security/advisories/GHSA-6hxr-mr5r-9836","https://github.com/uhop/node-re2/commit/56293de4fc0914d7bc35f92e98de25b0d9bb417d","https://github.com/uhop/node-re2/releases/tag/1.25.2"],"sourceUrl":"https://www.cve.org/CVERecord?id=CVE-2026-68499","license":"CVE Program Terms of Use","key":"cve-program:CVE-2026-68499","identifiers":["CVE-2026-68499"]},"retained":false,"historicalAffected":[]},{"revision":"a014780dbdcb4a84837195d15300aeca","observedAt":"2026-10-25T15:18:51.467+00:00","statement":{"source":"nvd","id":"CVE-2026-68499","aliases":[],"title":"re2 provides Node.js bindings for Google's RE2 regular expression engine. Prior to 1.25.2, re2's String.prototype.match implementation with a global RE2 pattern that can match the empty string fails to advance its native matching cursor in …","description":"re2 provides Node.js bindings for Google's RE2 regular expression engine. Prior to 1.25.2, re2's String.prototype.match implementation with a global RE2 pattern that can match the empty string fails to advance its native matching cursor in lib/match.cc, causing an infinite loop and unbounded native memory growth that blocks the event loop and can exhaust host memory. This issue is fixed in 1.25.2.","state":0,"publishedAt":"2026-07-30T21:18:12.87+00:00","modifiedAt":"2026-10-23T22:10:00.16+00:00","affected":[],"metrics":[{"system":"CVSS 3.1 · security-advisories@github.com · Secondary","vector":"CVSS:3.1/AV:L/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H","score":6.2,"severity":"MEDIUM"}],"references":["https://github.com/uhop/node-re2/commit/56293de4fc0914d7bc35f92e98de25b0d9bb417d","https://github.com/uhop/node-re2/releases/tag/1.25.2","https://github.com/uhop/node-re2/security/advisories/GHSA-6hxr-mr5r-9836"],"sourceUrl":"https://nvd.nist.gov/vuln/detail/CVE-2026-68499","license":"NIST NVD usage terms; underlying source attribution retained","enrichment":{"sourceStatus":"Awaiting Analysis","weaknesses":["CWE-835"],"productCriteria":[],"sourceDates":{"published":"2026-07-30T21:18:12.870","lastModified":"2026-10-23T22:10:00.160"},"relatedAdvisories":[],"note":"NVD analysis and CPE criteria are source context, not proof that a package or your environment is affected. Complete affected data, logical configurations and SSVC are retained in the original JSON."},"key":"nvd:CVE-2026-68499","identifiers":["CVE-2026-68499"]},"retained":false,"historicalAffected":[]},{"revision":"831df57a6ce2469e9ccf8953e9b31a8e","observedAt":"2026-10-24T13:17:17.793+00:00","statement":{"source":"osv","id":"GHSA-6hxr-mr5r-9836","aliases":["CVE-2026-68499"],"title":"re2: Global `String.prototype.match` with an empty-matchable pattern never advances → infinite loop with unbounded native memory growth (DoS)","description":"## Summary\n\n`String.prototype.match` with a **global** `RE2` collects all matches in a native loop that advances the cursor by the match length. A **zero-width (empty) match** has length 0, so the cursor never advances: the same empty match is found forever and appended to an ever-growing native vector. Any pattern that can match the empty string (`a*`, `b?`, `x{0,3}`, `(a)|`, `(?:)`, …) therefore causes an infinite loop with unbounded memory growth. The call is synchronous native code, so it blocks the entire event loop and cannot be interrupted by `try/catch`, `AbortController`, `--max-old-space-size`, or timers — the process must be killed externally. This diverges from the built-in engine, where `'xxxx'.match(/a*/g)` returns a finite array.\n\n## Root cause\n\n```cpp\n// lib/match.cc:44 — global branch of WrappedRE2::Match\nwhile (re2->regexp.Match(str, byteIndex, str.size, anchor, &match, 1)) {\n    groups.push_back(match);\n    byteIndex = match.data() - str.data + match.size();   // += 0 for a zero-width match\n}\n```\n\nWhen `match.size() == 0`, `byteIndex` is unchanged, so the next iteration matches the same empty position again; `groups` grows without bound. The other iteration paths already guard this: `lib/split.cc:50-55` advances by `getUtf8CharSize` on an empty match, and `exec` advances `lastIndex`. Only this global `Match` loop is missing the guard.\n\n## Proof of concept\n\n```js\nconst RE2 = require('re2');\n'x'.match(new RE2('a*', 'g'));   // never returns; grows memory until OOM\n// also: 'b?', 'x{0,3}', '(a)|', 'c*d*', '(?:)'; empty subject '' triggers it too\n```\n\nCompare with the built-in engine, which terminates:\n\n```js\n'xxxx'.match(/a*/g);   // -> [\"\", \"\", \"\", \"\", \"\"]\n```\n\nMeasured on a clean `npm install re2@1.25.1` (latest), stock prebuilt binary: resident memory grew **~550 MB → 2.3 GB in ~3 seconds** at 100% CPU, and the process had to be `SIGKILL`ed externally.\n\n## Impact\n\nDenial of service. Reachable remotely and without authentication wherever an application runs a **global** `RE2` through `String.prototype.match` and either the pattern or the subject is attacker-influenced — e.g. a user-supplied regular expression, or a fixed empty-matchable pattern applied to user input. Because the loop blocks the event loop and exhausts memory in seconds, a single request can wedge a worker and, via memory exhaustion, affect the whole host.\n\n## Suggested fix\n\nMirror the empty-match handling already present in `split.cc`: when the match is zero-width, advance the cursor by one code point.\n\n```cpp\n// lib/match.cc, inside the global while-loop\ngroups.push_back(match);\nsize_t off = match.data() - str.data;\nif (match.size()) {\n    byteIndex = off + match.size();\n} else {\n    byteIndex = off + (off < str.size ? getUtf8CharSize(str.data[off]) : 1);\n}\n```\n\n## Resolution\n\nFixed in re2 1.25.2.\n\nThe global match loop in `lib/match.cc` now advances the cursor by one Unicode\ncode point when a match is zero-width, so a pattern that can match the empty\nstring terminates with a finite result identical to the built-in engine\n(`'xxxx'.match(/a*/g)` returns five empty strings). This mirrors the guard\nalready present in `split`.\n\n**Remediation:** upgrade to `re2@1.25.2` or later.\n\n**Workaround** (if you cannot upgrade): do not run a global `RE2` through\n`String.prototype.match` when the pattern is attacker-influenced or can match\nthe empty string. Iterate with `matchAll`/`exec`, or use the non-global form;\nboth already advanced the cursor correctly.","state":0,"publishedAt":"2026-07-31T16:53:08+00:00","modifiedAt":"2026-07-31T17:00:21.7313101+00:00","affected":[{"ecosystem":"npm","name":"re2","ranges":[{"type":"SEMVER","events":[{"kind":"introduced","version":"0"},{"kind":"fixed","version":"1.25.2"}]}],"versions":[],"rawVersionEvidence":null}],"metrics":[{"system":"CVSS_V3","vector":"CVSS:3.1/AV:L/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H","score":null,"severity":null},{"system":"Publisher rating","vector":null,"score":null,"severity":"MODERATE"}],"references":["https://github.com/uhop/node-re2/security/advisories/GHSA-6hxr-mr5r-9836","https://nvd.nist.gov/vuln/detail/CVE-2026-68499","https://github.com/uhop/node-re2/commit/56293de4fc0914d7bc35f92e98de25b0d9bb417d","https://github.com/uhop/node-re2","https://github.com/uhop/node-re2/releases/tag/1.25.2"],"sourceUrl":"https://github.com/advisories/GHSA-6hxr-mr5r-9836","license":"GitHub Advisory Database · CC-BY-4.0","key":"osv:GHSA-6hxr-mr5r-9836","identifiers":["GHSA-6hxr-mr5r-9836","CVE-2026-68499"]},"retained":false,"historicalAffected":[]}],"coverage":[{"source":"cisa-kev:global","scope":"Complete CISA KEV catalog; all vendors. Missing entries do not establish absence of exploitation.","generation":"2026-10-26T13:35:31.4084177+00:00","complete":true,"records":1756,"lastAttemptAt":"2026-10-26T13:35:31.4084177+00:00","lastSuccessAt":"2026-10-26T13:35:31.5775932+00:00","error":null,"lastVerifiedAt":"2026-10-26T13:35:31.5775972+00:00","snapshotPublishedAt":null,"importing":false,"stagedRecords":0,"checkedIdentifiers":null,"expectedIdentifiers":null},{"source":"cve-program","scope":"Official CVE Program baseline and cumulative hourly delta; all vendors, published and rejected records","generation":"cve-5ba1945314e042c2ced14b33f3680fa71692812d925544312b218f5eb8a26e71-e7962156c388e029d9e5dbbcda79fbd40ade61bdd41d51546adb4696b3e29228","complete":true,"records":414161,"lastAttemptAt":"2026-10-26T13:35:30.7074205+00:00","lastSuccessAt":"2026-10-26T11:36:10.2537359+00:00","error":null,"lastVerifiedAt":"2026-10-26T13:35:30.7074205+00:00","snapshotPublishedAt":"2026-10-26T11:28:55+00:00","importing":false,"stagedRecords":0,"checkedIdentifiers":null,"expectedIdentifiers":null},{"source":"euvd","scope":"Rolling EUVD lookups of CVE aliases in current public OSV archives; 500 identifiers per refresh, rechecked after 48 hours. Not a global EUVD catalog. Successful not-found lookups count as checked; they do not imply withdrawal or safety. No reader inventory is sent.","generation":"enrichment-43321610382942b8ad8c85917eab1546","complete":false,"records":4735,"lastAttemptAt":"2026-10-26T13:35:59.8295777+00:00","lastSuccessAt":"2026-10-24T23:18:49.862+00:00","error":"InvalidDataException","lastVerifiedAt":"2026-10-24T23:18:49.862+00:00","snapshotPublishedAt":null,"importing":false,"stagedRecords":0,"checkedIdentifiers":4564,"expectedIdentifiers":13477},{"source":"first-epss:nuget","scope":"FIRST EPSS for explicit CVE aliases in the collected public NuGet archive. Not a global EPSS backfill.","generation":"2026-10-26T13:35:31.4084177+00:00","complete":true,"records":1093,"lastAttemptAt":"2026-10-26T13:35:31.4084177+00:00","lastSuccessAt":"2026-10-26T13:35:31.5784069+00:00","error":null,"lastVerifiedAt":"2026-10-26T13:35:31.5784074+00:00","snapshotPublishedAt":null,"importing":false,"stagedRecords":0,"checkedIdentifiers":null,"expectedIdentifiers":null},{"source":"nvd","scope":"Rolling NVD lookups of CVE aliases in current public OSV archives; 500 identifiers per refresh, rechecked after 48 hours. Not a global NVD catalog. Successful not-found lookups count as checked; they do not imply withdrawal or safety. No reader inventory is sent.","generation":"enrichment-03a3ea3298bf4e3f8edd073e1229d545","complete":true,"records":13416,"lastAttemptAt":"2026-10-26T13:35:57.9513146+00:00","lastSuccessAt":"2026-10-26T13:35:57.948+00:00","error":null,"lastVerifiedAt":"2026-10-26T13:35:57.948+00:00","snapshotPublishedAt":null,"importing":false,"stagedRecords":0,"checkedIdentifiers":13477,"expectedIdentifiers":13477},{"source":"osv:Go","scope":"Complete OSV Go ecosystem archive, including withdrawn and malicious-package source records; statement counts are not unique CVE counts","generation":"go-2375a4e597279abf92e8747e140fe8da9d421877cd49cae3ac69a2cb78469b2c","complete":true,"records":9779,"lastAttemptAt":"2026-10-26T13:35:31.3462861+00:00","lastSuccessAt":"2026-10-24T13:19:53.1346702+00:00","error":null,"lastVerifiedAt":"2026-10-26T13:35:31.3462861+00:00","snapshotPublishedAt":"2026-10-24T03:03:12+00:00","importing":false,"stagedRecords":0,"checkedIdentifiers":null,"expectedIdentifiers":null},{"source":"osv:NuGet","scope":"Complete OSV NuGet ecosystem archive, including GitHub Advisory Database records; NuGet version matching only","generation":"nuget-16ad89dfea13ab9e9b0108e63a759d63bd4559cc68b58491107d62ee35bbbaf2","complete":true,"records":1965,"lastAttemptAt":"2026-10-26T13:35:30.8546246+00:00","lastSuccessAt":"2026-10-23T16:01:26.4487605+00:00","error":null,"lastVerifiedAt":"2026-10-26T13:35:30.8546246+00:00","snapshotPublishedAt":"2026-10-21T12:18:07+00:00","importing":false,"stagedRecords":0,"checkedIdentifiers":null,"expectedIdentifiers":null},{"source":"osv:crates.io","scope":"Complete OSV crates.io ecosystem archive, including withdrawn and malicious-package source records; statement counts are not unique CVE counts","generation":"crates.io-7d18ad8657bc2f95d55948e9e16b3c82a8ac06830df5ec8d356048b8420b72c3","complete":true,"records":2972,"lastAttemptAt":"2026-10-26T13:35:31.3609129+00:00","lastSuccessAt":"2026-10-26T11:36:23.0131888+00:00","error":null,"lastVerifiedAt":"2026-10-26T13:35:31.3609129+00:00","snapshotPublishedAt":"2026-10-26T11:33:16+00:00","importing":false,"stagedRecords":0,"checkedIdentifiers":null,"expectedIdentifiers":null},{"source":"osv:npm","scope":"Complete OSV npm ecosystem archive, including withdrawn and malicious-package source records; statement counts are not unique CVE counts","generation":"npm-690135177074a0c4b9ddcb48232cb870c32b1a7adcd972a81c224810b8437d0d","complete":true,"records":230805,"lastAttemptAt":"2026-10-26T13:35:31.2341103+00:00","lastSuccessAt":"2026-10-26T12:37:54.7648812+00:00","error":null,"lastVerifiedAt":"2026-10-26T13:35:31.2341103+00:00","snapshotPublishedAt":"2026-10-26T11:48:32+00:00","importing":false,"stagedRecords":0,"checkedIdentifiers":null,"expectedIdentifiers":null}]}