CVE-2021-43843: Other (NVD-CWE-Other)
value: jsx-slack is a package for building JSON objects for Slack block kit surfaces from JSX. The maintainers found the patch for CVE-2021-43838 in jsx-slack v4.5.1 is insufficient tfor protection from a Regular Expression Denial of Service (ReDoS) attack. If an attacker can put a lot of JSX elements into `<blockquote>` tag _with including multibyte characters_, an internal regular expression for escaping characters may consume an excessive amount of computing resources. v4.5.1 passes the test against ASCII characters but misses the case of multibyte characters. jsx-slack v4.5.2 has updated regular expressions for escaping blockquote characters to prevent catastrophic backtracking. It is also including an updated test case to confirm rendering multiple tags in `<blockquote>` with multibyte characters.
CWE description: NVD is only using a subset of CWE for mapping instead of the entire CWE, and the weakness type is not covered by that subset.
CVSS v3 base score: 7.5
Published: 2021-12-20T22:15Z
Repository: https://github.com/yhatt/jsx-slack
Language: TypeScript
Files changed: src/mrkdwn/escape.ts
Commit date: 2021-12-18 16:03:24 +0900
Commit message: Prevent catastrophic backtracking in blockquote escape replacer

Diff: diff --git a/src/mrkdwn/escape.ts b/src/mrkdwn/escape.ts
index 5702c5f..abb2491 100644
--- a/src/mrkdwn/escape.ts
+++ b/src/mrkdwn/escape.ts
@@ -1,22 +1,23 @@
 // An internal HTML tag and emoji shorthand should not escape
 const preventEscapeRegex =
-  /(<.*?>|:[-a-z0-9ÀÁÂÃÄÇÈÉÊËÍÎÏÑÓÔÕÖŒœÙÚÛÜŸßàáâãäçèéêëíîïñóôõöùúûüÿ_＿+＋'\u1100-\u11ff\u2e80-\u2fd5\u3005\u3041-\u3096\u30a0-\u30ff\u3130-\u318f\u3400-\u4db5\u4e00-\u9fcb\ua960-\ua97f\uac00-\ud7ff\uff10-\uff19\uff41-\uff5a\uff61-\uff9f]+:)/
+  /(<[^>]*>|:[-a-z0-9ÀÁÂÃÄÇÈÉÊËÍÎÏÑÓÔÕÖŒœÙÚÛÜŸßàáâãäçèéêëíîïñóôõöùúûüÿ_＿+＋'\u1100-\u11ff\u2e80-\u2fd5\u3005\u3041-\u3096\u30a0-\u30ff\u3130-\u318f\u3400-\u4db5\u4e00-\u9fcb\ua960-\ua97f\uac00-\ud7ff\uff10-\uff19\uff41-\uff5a\uff61-\uff9f]+:)/
 
 const generateReplacerForEscape = (fallback: string) => (matched: string) =>
   `<span data-escape="${fallback.repeat(matched.length)}">${matched}</span>`
 
 export const escapeReplacers = {
   blockquote: (partial: string) =>
     partial
-      .replace(/^((?:<.*?>)*)(.{4})/gm, (matched, leading, character) =>
-        character === '&gt;' ? `${leading}\u00ad&gt;` : matched
+      .replace(
+        /^((?:<(?:[^>]|>(?=<))*>)?)(&gt;)/gm,
+        (_, leadingTags, character) => `${leadingTags}\u00ad${character}`
       )
       .replace(
-        /^((?:<.*?>)*)(＞)/gm,
-        (_, leading, character) =>
-          `${leading}${generateReplacerForEscape('\u00ad＞')(character)}`
+        /^((?:<(?:[^>]|>(?=<))*>)?)(＞)/gm,
+        (_, leadingTags, character) =>
+          `${leadingTags}${generateReplacerForEscape('\u00ad＞')(character)}`
       ),
   bold: (partial: string) =>
     partial
       .replace(/\*+/g, generateReplacerForEscape('\u2217'))
       .replace(/＊+/g, generateReplacerForEscape('\ufe61')),

Vulnerable code:   /(<.*?>|:[-a-z0-9ÀÁÂÃÄÇÈÉÊËÍÎÏÑÓÔÕÖŒœÙÚÛÜŸßàáâãäçèéêëíîïñóôõöùúûüÿ_＿+＋'\u1100-\u11ff\u2e80-\u2fd5\u3005\u3041-\u3096\u30a0-\u30ff\u3130-\u318f\u3400-\u4db5\u4e00-\u9fcb\ua960-\ua97f\uac00-\ud7ff\uff10-\uff19\uff41-\uff5a\uff61-\uff9f]+:)/
      .replace(/^((?:<.*?>)*)(.{4})/gm, (matched, leading, character) =>
        character === '&gt;' ? `${leading}\u00ad&gt;` : matched
        /^((?:<.*?>)*)(＞)/gm,
        (_, leading, character) =>
          `${leading}${generateReplacerForEscape('\u00ad＞')(character)}`
Fixed code:   /(<[^>]*>|:[-a-z0-9ÀÁÂÃÄÇÈÉÊËÍÎÏÑÓÔÕÖŒœÙÚÛÜŸßàáâãäçèéêëíîïñóôõöùúûüÿ_＿+＋'\u1100-\u11ff\u2e80-\u2fd5\u3005\u3041-\u3096\u30a0-\u30ff\u3130-\u318f\u3400-\u4db5\u4e00-\u9fcb\ua960-\ua97f\uac00-\ud7ff\uff10-\uff19\uff41-\uff5a\uff61-\uff9f]+:)/
      .replace(
        /^((?:<(?:[^>]|>(?=<))*>)?)(&gt;)/gm,
        (_, leadingTags, character) => `${leadingTags}\u00ad${character}`
        /^((?:<(?:[^>]|>(?=<))*>)?)(＞)/gm,
        (_, leadingTags, character) =>
          `${leadingTags}${generateReplacerForEscape('\u00ad＞')(character)}`