From a3cf4a5bf7f51f9ceb8283b0181baa3b7cf4a813 Mon Sep 17 00:00:00 2001 From: Mark Date: Mon, 6 Jul 2026 00:58:14 -0400 Subject: [PATCH 1/2] fix: replace `COMMENT_REGEX` to prevent ReDoS vulnerability - Replace nested quantifier pattern with lazy match to eliminate polynomial backtracking - Fix CodeQL: polynomial regular expression used on uncontrolled data --- index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/index.js b/index.js index d17e8fb..b8b0da0 100644 --- a/index.js +++ b/index.js @@ -1,6 +1,6 @@ // http://www.w3.org/TR/CSS21/grammar.html // https://github.com/visionmedia/css-parse/pull/49#issuecomment-30088027 -var COMMENT_REGEX = /\/\*[^*]*\*+([^/*][^*]*\*+)*\//g; +var COMMENT_REGEX = /\/\*[\s\S]*?\*\//g; var NEWLINE_REGEX = /\n/g; var WHITESPACE_REGEX = /^\s*/; From eb7d005ec951b47f20e3a6b4df99007be50741fa Mon Sep 17 00:00:00 2001 From: Mark Date: Mon, 6 Jul 2026 01:05:53 -0400 Subject: [PATCH 2/2] fix: prevent ReDoS in `COMMENT_REGEX` with unambiguous alternation - Replace lazy quantifier with mutually exclusive alternatives to eliminate backtracking - Add test cases for adversarial comment inputs --- index.js | 2 +- test/__snapshots__/index.test.js.snap | 42 +++++++++++++++++++++++++++ test/data.js | 10 ++++++- 3 files changed, 52 insertions(+), 2 deletions(-) diff --git a/index.js b/index.js index b8b0da0..d1887e2 100644 --- a/index.js +++ b/index.js @@ -1,6 +1,6 @@ // http://www.w3.org/TR/CSS21/grammar.html // https://github.com/visionmedia/css-parse/pull/49#issuecomment-30088027 -var COMMENT_REGEX = /\/\*[\s\S]*?\*\//g; +var COMMENT_REGEX = /\/\*(?:[^*]|\*(?!\/))*\*\//g; var NEWLINE_REGEX = /\n/g; var WHITESPACE_REGEX = /^\s*/; diff --git a/test/__snapshots__/index.test.js.snap b/test/__snapshots__/index.test.js.snap index c84cfd2..43eca80 100644 --- a/test/__snapshots__/index.test.js.snap +++ b/test/__snapshots__/index.test.js.snap @@ -1,5 +1,47 @@ // Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing +exports[`inline-style-parser parses adversarial comment input with mixed star-slash repetitions without backtracking 1`] = ` +[ + { + "position": Position { + "end": { + "column": 26, + "line": 1, + }, + "source": undefined, + "start": { + "column": 1, + "line": 1, + }, + }, + "property": "color", + "type": "declaration", + "value": "red", + }, +] +`; + +exports[`inline-style-parser parses adversarial comment input without backtracking 1`] = ` +[ + { + "position": Position { + "end": { + "column": 25, + "line": 1, + }, + "source": undefined, + "start": { + "column": 1, + "line": 1, + }, + }, + "property": "color", + "type": "declaration", + "value": "red", + }, +] +`; + exports[`inline-style-parser parses declaration with comment-only value 1`] = ` [ { diff --git a/test/data.js b/test/data.js index 415700b..0cc3599 100644 --- a/test/data.js +++ b/test/data.js @@ -84,7 +84,15 @@ const snapshots = [ ` ], - ['parses declaration with comment-only value', 'color: /* red */;'] + ['parses declaration with comment-only value', 'color: /* red */;'], + [ + 'parses adversarial comment input without backtracking', + 'color: /**)))**)))**/red;' + ], + [ + 'parses adversarial comment input with mixed star-slash repetitions without backtracking', + 'color: /**)*)/**)**)*/red;' + ] ]; const errors = [