Package: node-css-what
Version: 4.0.0-3
Severity: serious
Tags: security
Justification: security
X-Debbugs-Cc: Debian Security Team <t...@security.debian.org>

Dear Maintainer,

Find the minimal ReDoS fix for 4.0.0, checked with recheck

Bastien
>From eeb1fafd26a9f09114b6f8282a9569f99d52d716 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Bastien=20Roucari=C3=A8s?= <ro...@debian.org>
Date: Wed, 1 Mar 2023 11:45:48 +0000
Subject: [PATCH 5/5] Final ReDos Fix

Replace \s that could match whitespace in \u00b0-\uFFFF, by [ \t\n\r\f]* that is space according to css specification
---
 src/parse.ts | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/parse.ts b/src/parse.ts
index fcae1e3..278eecf 100644
--- a/src/parse.ts
+++ b/src/parse.ts
@@ -81,7 +81,7 @@ export type TraversalType =
 const reName = /^[^\\#]?(?:\\(?:[\da-f]{1,6}\s?|.)|[\w\-\u00b0-\uFFFF])+/;
 const reEscape = /\\([\da-f]{1,6}\s?|(\s)|.)/gi;
 // Modified version of https://github.com/jquery/sizzle/blob/master/src/sizzle.js#L87
-const reAttr = /^(?:(\*|[-\w]*)\|)?((?:\\.|[\w\u00b0-\uFFFF-])+)\s*(?:([~|^$*!]?)=\s*(?:(['"])((?:[^\\]|\\[^])*?)\4\s*|(#(?:\\.|[\w\u00b0-\uFFFF-])*|(?:\\.|[\w\u00b0-\uFFFF-])+)\s*|)|)([iI])?\]/;
+const reAttr = /^(?:(\*|[-\w]*)\|)?((?:\\.|[\w\u00b0-\uFFFF-])+)[ \t\n\r\f]*(?:([~|^$*!]?)=[ \t\n\r\f]*(?:(['"])((?:[^\\]|\\[^])*?)\4[ \t\n\r\f]*|(#(?:\\.|[\w\u00b0-\uFFFF-])*|(?:\\.|[\w\u00b0-\uFFFF-])+)[ \t\n\r\f]*|)|)([iI])?\]/;
 
 const actionTypes: { [key: string]: AttributeAction } = {
     undefined: "exists",
-- 
2.39.2

>From 68319750685dc65fa63e1ef12686ca0ddae11007 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Bastien=20Roucari=C3=A8s?= <ro...@debian.org>
Date: Wed, 1 Mar 2023 08:12:48 +0000
Subject: [PATCH 1/5] Partial fix of reDos

Per https://w3c.github.io/csswg-drafts/selectors/#attribute-selectors only = ~= |= ^= $= *= are supported.

Add also != that is checked as invalid latter in order to pass testsuite.

So replace \S by [~|^$*!]
---
 src/parse.ts | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/parse.ts b/src/parse.ts
index 677a029..628561b 100644
--- a/src/parse.ts
+++ b/src/parse.ts
@@ -81,7 +81,7 @@ export type TraversalType =
 const reName = /^[^\\#]?(?:\\(?:[\da-f]{1,6}\s?|.)|[\w\-\u00b0-\uFFFF])+/;
 const reEscape = /\\([\da-f]{1,6}\s?|(\s)|.)/gi;
 // Modified version of https://github.com/jquery/sizzle/blob/master/src/sizzle.js#L87
-const reAttr = /^\s*(?:(\*|[-\w]*)\|)?((?:\\.|[\w\u00b0-\uFFFF-])+)\s*(?:(\S?)=\s*(?:(['"])((?:[^\\]|\\[^])*?)\4|(#?(?:\\.|[\w\u00b0-\uFFFF-])*)|)|)\s*([iI])?\]/;
+const reAttr = /^\s*(?:(\*|[-\w]*)\|)?((?:\\.|[\w\u00b0-\uFFFF-])+)\s*(?:([~|^$*!]?)=\s*(?:(['"])((?:[^\\]|\\[^])*?)\4|(#?(?:\\.|[\w\u00b0-\uFFFF-])*)|)|)\s*([iI])?\]/;
 
 const actionTypes: { [key: string]: AttributeAction } = {
     undefined: "exists",
-- 
2.39.2

>From 2d4e734ab30e8b19cdfedccc19923d2d69f40510 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Bastien=20Roucari=C3=A8s?= <ro...@debian.org>
Date: Wed, 1 Mar 2023 10:10:47 +0000
Subject: [PATCH 2/5] Partial fix of ReDos

Trim left the string avoiding a \s* at the beginning of the string, thus avoiding part of complexity.
---
 src/parse.ts | 11 ++++++++---
 1 file changed, 8 insertions(+), 3 deletions(-)

diff --git a/src/parse.ts b/src/parse.ts
index 628561b..ad11230 100644
--- a/src/parse.ts
+++ b/src/parse.ts
@@ -81,7 +81,7 @@ export type TraversalType =
 const reName = /^[^\\#]?(?:\\(?:[\da-f]{1,6}\s?|.)|[\w\-\u00b0-\uFFFF])+/;
 const reEscape = /\\([\da-f]{1,6}\s?|(\s)|.)/gi;
 // Modified version of https://github.com/jquery/sizzle/blob/master/src/sizzle.js#L87
-const reAttr = /^\s*(?:(\*|[-\w]*)\|)?((?:\\.|[\w\u00b0-\uFFFF-])+)\s*(?:([~|^$*!]?)=\s*(?:(['"])((?:[^\\]|\\[^])*?)\4|(#?(?:\\.|[\w\u00b0-\uFFFF-])*)|)|)\s*([iI])?\]/;
+const reAttr = /^(?:(\*|[-\w]*)\|)?((?:\\.|[\w\u00b0-\uFFFF-])+)\s*(?:([~|^$*!]?)=\s*(?:(['"])((?:[^\\]|\\[^])*?)\4|(#?(?:\\.|[\w\u00b0-\uFFFF-])*)|)|)\s*([iI])?\]/;
 
 const actionTypes: { [key: string]: AttributeAction } = {
     undefined: "exists",
@@ -263,8 +263,13 @@ function parseSelector(
                     namespace: null,
                 });
             } else if (firstChar === "[") {
+		const wmatch = selector
+		      .slice(selectorIndex + 1)
+		      .match(/^\s*/);
+		const woffset = !wmatch ? 0 : wmatch[0].length;
+
                 const attributeMatch = selector
-                    .slice(selectorIndex + 1)
+                    .slice(selectorIndex + 1 + woffset)
                     .match(reAttr);
 
                 if (!attributeMatch) {
@@ -286,7 +291,7 @@ function parseSelector(
                     ignoreCase,
                 ] = attributeMatch;
 
-                selectorIndex += completeSelector.length + 1;
+                selectorIndex += completeSelector.length + 1 + woffset;
                 let name = unescapeCSS(baseName);
 
                 if (options.lowerCaseAttributeNames ?? !options.xmlMode) {
-- 
2.39.2

>From 05ff66f7eb1533866713de590fdc26e779db8516 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Bastien=20Roucari=C3=A8s?= <ro...@debian.org>
Date: Wed, 1 Mar 2023 10:34:56 +0000
Subject: [PATCH 3/5] Partial Fix of ReDos

Push \s* inside the group
---
 src/parse.ts | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/parse.ts b/src/parse.ts
index ad11230..4bca92f 100644
--- a/src/parse.ts
+++ b/src/parse.ts
@@ -81,7 +81,7 @@ export type TraversalType =
 const reName = /^[^\\#]?(?:\\(?:[\da-f]{1,6}\s?|.)|[\w\-\u00b0-\uFFFF])+/;
 const reEscape = /\\([\da-f]{1,6}\s?|(\s)|.)/gi;
 // Modified version of https://github.com/jquery/sizzle/blob/master/src/sizzle.js#L87
-const reAttr = /^(?:(\*|[-\w]*)\|)?((?:\\.|[\w\u00b0-\uFFFF-])+)\s*(?:([~|^$*!]?)=\s*(?:(['"])((?:[^\\]|\\[^])*?)\4|(#?(?:\\.|[\w\u00b0-\uFFFF-])*)|)|)\s*([iI])?\]/;
+const reAttr = /^(?:(\*|[-\w]*)\|)?((?:\\.|[\w\u00b0-\uFFFF-])+)\s*(?:([~|^$*!]?)=\s*(?:(['"])((?:[^\\]|\\[^])*?)\4\s*|(#?(?:\\.|[\w\u00b0-\uFFFF-])*)\s*|)|)([iI])?\]/;
 
 const actionTypes: { [key: string]: AttributeAction } = {
     undefined: "exists",
-- 
2.39.2

>From 55dc363dcde4b2dde3c36c12216bd12b184485e4 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Bastien=20Roucari=C3=A8s?= <ro...@debian.org>
Date: Wed, 1 Mar 2023 11:40:39 +0000
Subject: [PATCH 4/5] Partial ReDoS fix

Replace possibly null combinaison (#?(?:\\.|[\w\u00b0-\uFFFF-])*) by (#(?:\\.|[\w\u00b0-\uFFFF-])*|(?:\\.|[\w\u00b0-\uFFFF-])+)
---
 src/parse.ts | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/parse.ts b/src/parse.ts
index 4bca92f..fcae1e3 100644
--- a/src/parse.ts
+++ b/src/parse.ts
@@ -81,7 +81,7 @@ export type TraversalType =
 const reName = /^[^\\#]?(?:\\(?:[\da-f]{1,6}\s?|.)|[\w\-\u00b0-\uFFFF])+/;
 const reEscape = /\\([\da-f]{1,6}\s?|(\s)|.)/gi;
 // Modified version of https://github.com/jquery/sizzle/blob/master/src/sizzle.js#L87
-const reAttr = /^(?:(\*|[-\w]*)\|)?((?:\\.|[\w\u00b0-\uFFFF-])+)\s*(?:([~|^$*!]?)=\s*(?:(['"])((?:[^\\]|\\[^])*?)\4\s*|(#?(?:\\.|[\w\u00b0-\uFFFF-])*)\s*|)|)([iI])?\]/;
+const reAttr = /^(?:(\*|[-\w]*)\|)?((?:\\.|[\w\u00b0-\uFFFF-])+)\s*(?:([~|^$*!]?)=\s*(?:(['"])((?:[^\\]|\\[^])*?)\4\s*|(#(?:\\.|[\w\u00b0-\uFFFF-])*|(?:\\.|[\w\u00b0-\uFFFF-])+)\s*|)|)([iI])?\]/;
 
 const actionTypes: { [key: string]: AttributeAction } = {
     undefined: "exists",
-- 
2.39.2

Reply via email to