From 94021d22392497033685c6a90229ab211ba995de Mon Sep 17 00:00:00 2001 From: Ben Cooke Date: Wed, 6 May 2026 16:50:56 -0400 Subject: [PATCH 1/4] MM-68425 Harden markdown bracket parsing Co-authored-by: Cursor --- lib/marked.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/marked.js b/lib/marked.js index 74424dab38..a257930c2c 100644 --- a/lib/marked.js +++ b/lib/marked.js @@ -518,7 +518,7 @@ inline.tag = edit(inline.tag) inline._punctuation = '!"#$%&\'()*+,\\-./:;<=>?@\\[^_{|}~'; inline.em = edit(inline.em).replace(/punctuation/g, inline._punctuation).getRegex(); -inline._inside = /(?:\[[^\]]*\]|[^\[\]]|\](?=[^\[]*\]))*/; +inline._inside = /(?:\[(?:\\.|[^\[\]\\])*\]|\\.|`[^`]*`|[^\[\]\\`])*/; inline._href = /(?:[^()]|\([^()]*\)|\((?:[^()]*\([^()]*\))+[^()]*\))*/; inline.link = replace(inline.link) ('inside', inline._inside) From 5da80f805706dae9e3d1bf8503a3ead4a4248573 Mon Sep 17 00:00:00 2001 From: Ben Cooke Date: Wed, 6 May 2026 16:58:04 -0400 Subject: [PATCH 2/4] MM-68425 Harden markdown reference parsing Co-authored-by: Cursor --- lib/marked.js | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/lib/marked.js b/lib/marked.js index a257930c2c..2d375da630 100644 --- a/lib/marked.js +++ b/lib/marked.js @@ -21,7 +21,7 @@ var block = { blockquote: /^( *>[^\n]+(\n(?!def)[^\n]+)*\n*)+/, list: /^( *)(bull) [\s\S]+?(?:hr|def|\n{2,}(?! )(?!\1bull )\n*|\s*$)/, html: /^ *(?:comment *(?:\n|\s*$)|closed *(?:\n{2,}|\s*$)|closing *(?:\n{2,}|\s*$))/, - def: /^ *\[([^\]]+)\]: *]+)>?(?: +["(]([^\n]+)[")])? *(?:\n+|$)/, + def: /^ *\[((?!\s*\])(?:\\.|[^\[\]\\])+)\]: *]+)>?(?: +["(]([^\n]+)[")])? *(?:\n+|$)/, table: noop, paragraph: /^((?:[^\n]+\n?(?!hr|heading|lheading|blockquote|tag|def))+)\n*/, text: /^[^\n]+/ @@ -495,8 +495,8 @@ var inline = { + '|^' // declaration, e.g. + '|^', // CDATA section link: /^!?\[(inside)\]\((href)\)/, - reflink: /^!?\[(inside)\]\s*\[([^\]]*)\]/, - nolink: /^!?\[((?:\[[^\]]*\]|[^\[\]])*)\]/, + reflink: /^!?\[(inside)\]\s*\[(label)\]/, + nolink: /^!?\[(inside)\]/, strong: /^__([\s\S]+?)__(?!_)|^\*\*([\s\S]+?)\*\*(?!\*)/, em: /^_([^\s_])_(?!_)|^\*([^\s*"<])\*(?!\*)|^_([^\s][\s\S]*?[^\s_])_(?!_|[^\spunctuation])|^_([^\s_][\s\S]*?[^\s])_(?!_|[^\spunctuation])|^\*([^\s"<][\s\S]*?[^\s*])\*(?!\*)|^\*([^\s*"<][\s\S]*?[^\s])\*(?!\*)/, code: /^(`+)([^`]|[^`][\s\S]*?[^`])\1(?!`)/, @@ -519,6 +519,7 @@ inline._punctuation = '!"#$%&\'()*+,\\-./:;<=>?@\\[^_{|}~'; inline.em = edit(inline.em).replace(/punctuation/g, inline._punctuation).getRegex(); inline._inside = /(?:\[(?:\\.|[^\[\]\\])*\]|\\.|`[^`]*`|[^\[\]\\`])*/; +inline._label = /(?:\\.|[^\[\]\\])*/; inline._href = /(?:[^()]|\([^()]*\)|\((?:[^()]*\([^()]*\))+[^()]*\))*/; inline.link = replace(inline.link) ('inside', inline._inside) @@ -529,6 +530,11 @@ inline.link = replace(inline.link) inline.href = /^\s*?(?:\s+['"]([\s\S]*?)['"])?\s*$/; inline.reflink = replace(inline.reflink) + ('inside', inline._inside) + ('label', inline._label) + (); + +inline.nolink = replace(inline.nolink) ('inside', inline._inside) (); From cdbfe5657c6e73db01a0719148b60c4a71921ba7 Mon Sep 17 00:00:00 2001 From: Ben Cooke Date: Mon, 11 May 2026 14:55:28 -0400 Subject: [PATCH 3/4] MM-68425 Harden markdown code span parsing Co-authored-by: Cursor --- lib/marked.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/marked.js b/lib/marked.js index 2d375da630..74e771ecca 100644 --- a/lib/marked.js +++ b/lib/marked.js @@ -518,7 +518,7 @@ inline.tag = edit(inline.tag) inline._punctuation = '!"#$%&\'()*+,\\-./:;<=>?@\\[^_{|}~'; inline.em = edit(inline.em).replace(/punctuation/g, inline._punctuation).getRegex(); -inline._inside = /(?:\[(?:\\.|[^\[\]\\])*\]|\\.|`[^`]*`|[^\[\]\\`])*/; +inline._inside = /(?:\[(?:\\.|[^\[\]\\])*\]|\\.|`+[^`]*?`+(?!`)|[^\[\]\\`])*/; inline._label = /(?:\\.|[^\[\]\\])*/; inline._href = /(?:[^()]|\([^()]*\)|\((?:[^()]*\([^()]*\))+[^()]*\))*/; inline.link = replace(inline.link) From ac58045c620edf3bbecb48131086e578c9a26167 Mon Sep 17 00:00:00 2001 From: Ben Cooke Date: Wed, 27 May 2026 13:32:09 -0400 Subject: [PATCH 4/4] MM-68425 Update markdown parsing coverage Co-authored-by: Cursor --- lib/marked.js | 20 ++++++++++---------- test/tests/catastrophic.text | 1 + 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/lib/marked.js b/lib/marked.js index 74e771ecca..278027363f 100644 --- a/lib/marked.js +++ b/lib/marked.js @@ -21,7 +21,7 @@ var block = { blockquote: /^( *>[^\n]+(\n(?!def)[^\n]+)*\n*)+/, list: /^( *)(bull) [\s\S]+?(?:hr|def|\n{2,}(?! )(?!\1bull )\n*|\s*$)/, html: /^ *(?:comment *(?:\n|\s*$)|closed *(?:\n{2,}|\s*$)|closing *(?:\n{2,}|\s*$))/, - def: /^ *\[((?!\s*\])(?:\\.|[^\[\]\\])+)\]: *]+)>?(?: +["(]([^\n]+)[")])? *(?:\n+|$)/, + def: /^ *\[([^\]]+)\]: *]+)>?(?: +["(]([^\n]+)[")])? *(?:\n+|$)/, table: noop, paragraph: /^((?:[^\n]+\n?(?!hr|heading|lheading|blockquote|tag|def))+)\n*/, text: /^[^\n]+/ @@ -494,9 +494,9 @@ var inline = { + '|^<\\?[\\s\\S]*?\\?>' // processing instruction, e.g. + '|^' // declaration, e.g. + '|^', // CDATA section - link: /^!?\[(inside)\]\((href)\)/, - reflink: /^!?\[(inside)\]\s*\[(label)\]/, - nolink: /^!?\[(inside)\]/, + link: /^!?\[(label)\]\((href)\)/, + reflink: /^!?\[(label)\]\s*\[(ref)\]/, + nolink: /^!?\[(ref)\]/, strong: /^__([\s\S]+?)__(?!_)|^\*\*([\s\S]+?)\*\*(?!\*)/, em: /^_([^\s_])_(?!_)|^\*([^\s*"<])\*(?!\*)|^_([^\s][\s\S]*?[^\s_])_(?!_|[^\spunctuation])|^_([^\s_][\s\S]*?[^\s])_(?!_|[^\spunctuation])|^\*([^\s"<][\s\S]*?[^\s*])\*(?!\*)|^\*([^\s*"<][\s\S]*?[^\s])\*(?!\*)/, code: /^(`+)([^`]|[^`][\s\S]*?[^`])\1(?!`)/, @@ -518,11 +518,11 @@ inline.tag = edit(inline.tag) inline._punctuation = '!"#$%&\'()*+,\\-./:;<=>?@\\[^_{|}~'; inline.em = edit(inline.em).replace(/punctuation/g, inline._punctuation).getRegex(); -inline._inside = /(?:\[(?:\\.|[^\[\]\\])*\]|\\.|`+[^`]*?`+(?!`)|[^\[\]\\`])*/; -inline._label = /(?:\\.|[^\[\]\\])*/; +var _inlineLabel = /(?:\[(?:\\.|[^\[\]\\])*\]|\\.|`+[^`]*?`+(?!`)|[^\[\]\\`])*/; +var _blockLabel = /(?:\\.|[^\[\]\\])*/; inline._href = /(?:[^()]|\([^()]*\)|\((?:[^()]*\([^()]*\))+[^()]*\))*/; inline.link = replace(inline.link) - ('inside', inline._inside) + ('label', _inlineLabel) ('href', inline._href) (); @@ -530,12 +530,12 @@ inline.link = replace(inline.link) inline.href = /^\s*?(?:\s+['"]([\s\S]*?)['"])?\s*$/; inline.reflink = replace(inline.reflink) - ('inside', inline._inside) - ('label', inline._label) + ('label', _inlineLabel) + ('ref', _blockLabel) (); inline.nolink = replace(inline.nolink) - ('inside', inline._inside) + ('ref', _blockLabel) (); /** diff --git a/test/tests/catastrophic.text b/test/tests/catastrophic.text index 483b161ca9..83680575cf 100644 --- a/test/tests/catastrophic.text +++ b/test/tests/catastrophic.text @@ -1,4 +1,5 @@ [link](http://example.com/url) +[``a]b``](http://example.com/url) [link](http://example.com/url [link](http://example.com/ur [link](http://example.com/u