simple-markdown simple-markdown.js redos
Description
A ReDoS vulnerability in simple-markdown 0.5.1 allows remote attackers to cause denial of service via crafted inline code blocks.
AI Insight
LLM-synthesized narrative grounded in this CVE's description and references.
A ReDoS vulnerability in simple-markdown 0.5.1 allows remote attackers to cause denial of service via crafted inline code blocks.
The vulnerability lies in the regular expression handling within simple-markdown.js, where inefficient regex complexity leads to excessive backtracking when processing crafted input [2]. Specifically, the parser's handling of inline code blocks is vulnerable to exponential backtracking, enabling a regular expression denial of service (ReDoS) attack [3].
An attacker can exploit this remotely by sending a specially crafted markdown string containing a long sequence of backticks or inline code delimiter abuse, causing the regex engine to consume excessive CPU resources [2]. No authentication is required, making the attack surface broad for any service that uses simple-markdown to parse user-supplied markdown.
Successful exploitation results in high CPU utilization or temporary unresponsiveness of the parsing process, potentially leading to denial of service for other users of the application. The vulnerability is classified with a CVSS score pending, but the impact is primarily availability [2].
The issue is addressed in version 0.5.2, which fixes the regex vulnerabilities [4]. The maintainers recommend upgrading to version 0.5.3, which contains a further bugfix on the inline code change [4]. A patch commit (89797fef9abb4cab2fb76a335968266a92588816) is available for reference [2].
AI Insight generated on May 20, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.
Affected packages
Versions sourced from the GitHub Security Advisory.
| Package | Affected versions | Patched versions |
|---|---|---|
simple-markdownnpm | < 0.5.2 | 0.5.2 |
Affected products
2- simple-markdown/simple-markdowndescription
Patches
201bcc3e74e1cv0.5.2: Fix exponential backtracking / ReDoS regexes
2 files changed · +2 −2
package.json+1 −1 modified@@ -1,6 +1,6 @@ { "name": "simple-markdown", - "version": "0.5.1", + "version": "0.5.2", "description": "Javascript markdown parsing, made simple", "main": "simple-markdown.js", "scripts": {
simple-markdown.min.js+1 −1 modified@@ -1 +1 @@ -!function(){var p,u,n,e,r,d,h,t,a=/\r\n?/g,l=/\t/g,o=/\f/g,c=function(t){return t.replace(a,"\n").replace(o,"").replace(l," ")},i=function(t,n){var e=t||{};if(null!=n)for(var r in n)Object.prototype.hasOwnProperty.call(n,r)&&(e[r]=n[r]);return e},f=function(m,e){var y,g=Object.keys(m).filter(function(t){var n=m[t];if(null==n||null==n.match)return!1;var e=n.order;return"number"==typeof e&&isFinite(e)||"undefined"==typeof console||console.warn("simple-markdown: Invalid order for rule `"+t+"`: "+String(e)),!0});g.sort(function(t,n){var e=m[t],r=m[n],a=e.order,l=r.order;if(a!==l)return a-l;var o=e.quality?0:1,u=r.quality?0:1;return o!==u?o-u:t<n?-1:n<t?1:0});var v=function(t,n){var e=[];y=n=n||y;for(var r="";t;){var a=null,l=null,o=null,u=NaN,c=0,i=g[0],f=m[i];do{var s=f.order,p=f.match(t,n,r);if(p){var d=f.quality?f.quality(p,n,r):0;d<=u||(a=i,l=f,o=p,u=d)}i=g[++c],f=m[i]}while(f&&(!o||f.order===s&&f.quality));if(!0!==n.disableErrorGuards){if(null==l||null==o)throw new Error("Could not find a matching rule for the below content. The rule with highest `order` should always match content provided to it. Check the definition of `match` for '"+g[g.length-1]+"'. It seems to not match the following source:\n"+t);if(0!==o.index&&t.slice(0,o[0].length)!==o[0])throw new Error("`match` must return a capture starting at index 0 (the current parse index). Did you forget a ^ at the start of the RegExp?")}var h=l.parse(o,v,n);Array.isArray(h)?Array.prototype.push.apply(e,h):(null==h.type&&(h.type=a),e.push(h)),r=o[0],t=t.substring(r.length)}return e};return function(t,n){return(y=i(n,e)).inline||y.disableAutoBlockNewlines||(t+="\n\n"),v(c(t),y)}},s=function(e){var t=function(t,n){return n.inline?e.exec(t):null};return t.regex=e,t},m=function(e){var t=function(t,n){return n.inline?null:e.exec(t)};return t.regex=e,t},y=function(e){var t=function(t,n){return e.exec(t)};return t.regex=e,t},g="function"==typeof Symbol&&Symbol.for&&Symbol.for("react.element")||60103,v=function(t,n,e){return{$$typeof:g,type:t,key:n,ref:null,props:e,_owner:null}},k=function(t,n,e,r){e=e||{},r=void 0===r||r;var a="";for(var l in e){var o=e[l];Object.prototype.hasOwnProperty.call(e,l)&&o&&(a+=" "+E(l)+'="'+E(o)+'"')}var u="<"+t+a+">";return r?u+n+"</"+t+">":u},x={},w=function(t){if(null==t)return null;try{var n=decodeURIComponent(t).replace(/[^A-Za-z0-9/:]/g,"").toLowerCase();if(0===n.indexOf("javascript:")||0===n.indexOf("vbscript:")||0===n.indexOf("data:"))return null}catch(t){return null}return t},b=/[<>&"']/g,_={"<":"<",">":">","&":"&",'"':""","'":"'","/":"/","`":"`"},E=function(t){return String(t).replace(b,function(t){return _[t]})},S=/\\([^0-9A-Za-z\s])/g,R=function(t){return t.replace(S,"$1")},A=function(t,n,e){var r=e.inline||!1;e.inline=!0;var a=t(n,e);return e.inline=r,a},O=function(t,n,e){return{content:A(n,t[1],e)}},T=function(){return{}},$="(?:[*+-]|\\d+\\.)",P="( *)("+$+") +",j=new RegExp("^"+P),q=new RegExp(P+"[^\\n]*(?:\\n(?!\\1"+$+" )[^\\n]*)*(\n|$)","gm"),B=/\n{2,}$/,F=B,N=/ *\n+$/,C=new RegExp("^( *)("+$+") [\\s\\S]+?(?:\n{2,}(?! )(?!\\1"+$+" )\\n*|\\s*\n*$)"),I=/(?:^|\n)( *)$/,L=(p=/^ *\| *| *\| *$/g,u=/ *$/,n=/^ *-+: *$/,e=/^ *:-+: *$/,r=/^ *:-+ *$/,d=function(t){return n.test(t)?"right":e.test(t)?"center":r.test(t)?"left":null},h=function(t,n,e,r){var a=e.inTable;e.inTable=!0;var l=n(t.trim(),e);e.inTable=a;var o=[[]];return l.forEach(function(t,n){"tableSeparator"===t.type?(!r||0!==n&&n!==l.length-1)&&o.push([]):("text"!==t.type||null!=l[n+1]&&"tableSeparator"!==l[n+1].type||(t.content=t.content.replace(u,"")),o[o.length-1].push(t))}),o},{parseTable:(t=function(s){return function(t,n,e){e.inline=!0;var r,a,l,o,u,c=h(t[1],n,e,s),i=(r=t[2],s&&(r=r.replace(p,"")),r.trim().split("|").map(d)),f=(a=t[3],l=n,o=e,u=s,a.trim().split("\n").map(function(t){return h(t,l,o,u)}));return e.inline=!1,{type:"table",header:c,align:i,cells:f}}})(!0),parseNpTable:t(!1),TABLE_REGEX:/^ *(\|.+)\n *\|( *[-:]+[-| :]*)\n((?: *\|.*(?:\n|$))*)\n*/,NPTABLE_REGEX:/^ *(\S.*\|.*)\n *([-:]+ *\|[-| :]*)\n((?:.*\|.*(?:\n|$))*)\n*/}),z="(?:\\[[^\\]]*\\]|[^\\[\\]]|\\](?=[^\\[]*\\]))*",G="\\s*<?((?:[^\\s\\\\]|\\\\.)*?)>?(?:\\s+['\"]([\\s\\S]*?)['\"])?\\s*",X=/mailto:/i,Z=function(t,n,e){var r=(t[2]||t[1]).replace(/\s+/g," ").toLowerCase();if(n._defs&&n._defs[r]){var a=n._defs[r];e.target=a.target,e.title=a.title}return n._refs=n._refs||{},n._refs[r]=n._refs[r]||[],n._refs[r].push(e),e},M=0,U={Array:{react:function(t,n,e){for(var r=e.key,a=[],l=0,o=0;l<t.length;l++,o++){e.key=""+l;var u=t[l];if("text"===u.type)for(u={type:"text",content:u.content};l+1<t.length&&"text"===t[l+1].type;l++)u.content+=t[l+1].content;a.push(n(u,e))}return e.key=r,a},html:function(t,n,e){for(var r="",a=0;a<t.length;a++){var l=t[a];if("text"===l.type)for(l={type:"text",content:l.content};a+1<t.length&&"text"===t[a+1].type;a++)l.content+=t[a+1].content;r+=n(l,e)}return r}},heading:{order:M++,match:m(/^ *(#{1,6}) *([^\n]+?) *#* *(?:\n *)+\n/),parse:function(t,n,e){return{level:t[1].length,content:A(n,t[2],e)}},react:function(t,n,e){return v("h"+t.level,e.key,{children:n(t.content,e)})},html:function(t,n,e){return k("h"+t.level,n(t.content,e))}},nptable:{order:M++,match:m(L.NPTABLE_REGEX),parse:L.parseNpTable,react:null,html:null},lheading:{order:M++,match:m(/^([^\n]+)\n *(=|-){3,} *(?:\n *)+\n/),parse:function(t,n,e){return{type:"heading",level:"="===t[2]?1:2,content:A(n,t[1],e)}},react:null,html:null},hr:{order:M++,match:m(/^( *[-*_]){3,} *(?:\n *)+\n/),parse:T,react:function(t,n,e){return v("hr",e.key,x)},html:function(t,n,e){return"<hr>"}},codeBlock:{order:M++,match:m(/^(?: [^\n]+\n*)+(?:\n *)+\n/),parse:function(t,n,e){return{lang:void 0,content:t[0].replace(/^ /gm,"").replace(/\n+$/,"")}},react:function(t,n,e){var r=t.lang?"markdown-code-"+t.lang:void 0;return v("pre",e.key,{children:v("code",null,{className:r,children:t.content})})},html:function(t,n,e){var r=t.lang?"markdown-code-"+t.lang:void 0,a=k("code",E(t.content),{class:r});return k("pre",a)}},fence:{order:M++,match:m(/^ *(`{3,}|~{3,}) *(\S+)? *\n([\s\S]+?)\s*\1 *(?:\n *)+\n/),parse:function(t,n,e){return{type:"codeBlock",lang:t[2]||void 0,content:t[3]}},react:null,html:null},blockQuote:{order:M++,match:m(/^( *>[^\n]+(\n[^\n]+)*\n*)+\n{2,}/),parse:function(t,n,e){return{content:n(t[0].replace(/^ *> ?/gm,""),e)}},react:function(t,n,e){return v("blockquote",e.key,{children:n(t.content,e)})},html:function(t,n,e){return k("blockquote",n(t.content,e))}},list:{order:M++,match:function(t,n,e){var r=I.exec(e),a=n._list||!n.inline;return r&&a?(t=r[1]+t,C.exec(t),C.exec(t)):null},parse:function(t,p,d){var n=t[2],e=1<n.length,r=e?+n:void 0,h=t[0].replace(F,"\n").match(q),m=!1;return{ordered:e,start:r,items:h.map(function(t,n){var e=j.exec(t),r=e?e[0].length:0,a=new RegExp("^ {1,"+r+"}","gm"),l=t.replace(a,"").replace(j,""),o=n===h.length-1,u=-1!==l.indexOf("\n\n")||o&&m;m=u;var c,i=d.inline,f=d._list;d._list=!0,c=u?(d.inline=!1,l.replace(N,"\n\n")):(d.inline=!0,l.replace(N,""));var s=p(c,d);return d.inline=i,d._list=f,s})}},react:function(t,e,r){var n=t.ordered?"ol":"ul";return v(n,r.key,{start:t.start,children:t.items.map(function(t,n){return v("li",""+n,{children:e(t,r)})})})},html:function(t,n,e){var r=t.items.map(function(t){return k("li",n(t,e))}).join(""),a=t.ordered?"ol":"ul",l={start:t.start};return k(a,r,l)}},def:{order:M++,match:m(/^ *\[([^\]]+)\]: *<?([^\s>]*)>?(?: +["(]([^\n]+)[")])? *\n(?: *\n)*/),parse:function(t,n,e){var r=t[1].replace(/\s+/g," ").toLowerCase(),a=t[2],l=t[3];return e._refs&&e._refs[r]&&e._refs[r].forEach(function(t){t.target=a,t.title=l}),e._defs=e._defs||{},e._defs[r]={target:a,title:l},{def:r,target:a,title:l}},react:function(){return null},html:function(){return""}},table:{order:M++,match:m(L.TABLE_REGEX),parse:L.parseTable,react:function(n,e,r){var a=function(t){return null==n.align[t]?{}:{textAlign:n.align[t]}},t=n.header.map(function(t,n){return v("th",""+n,{style:a(n),scope:"col",children:e(t,r)})}),l=n.cells.map(function(t,n){return v("tr",""+n,{children:t.map(function(t,n){return v("td",""+n,{style:a(n),children:e(t,r)})})})});return v("table",r.key,{children:[v("thead","thead",{children:v("tr",null,{children:t})}),v("tbody","tbody",{children:l})]})},html:function(n,e,r){var a=function(t){return null==n.align[t]?"":"text-align:"+n.align[t]+";"},t=n.header.map(function(t,n){return k("th",e(t,r),{style:a(n),scope:"col"})}).join(""),l=n.cells.map(function(t){var n=t.map(function(t,n){return k("td",e(t,r),{style:a(n)})}).join("");return k("tr",n)}).join(""),o=k("thead",k("tr",t)),u=k("tbody",l);return k("table",o+u)}},newline:{order:M++,match:m(/^(?:\n *)*\n/),parse:T,react:function(t,n,e){return"\n"},html:function(t,n,e){return"\n"}},paragraph:{order:M++,match:m(/^((?:[^\n]|\n(?! *\n))+)(?:\n *)+\n/),parse:O,react:function(t,n,e){return v("div",e.key,{className:"paragraph",children:n(t.content,e)})},html:function(t,n,e){return k("div",n(t.content,e),{class:"paragraph"})}},escape:{order:M++,match:s(/^\\([^0-9A-Za-z\s])/),parse:function(t,n,e){return{type:"text",content:t[1]}},react:null,html:null},tableSeparator:{order:M++,match:function(t,n){return n.inTable?/^ *\| */.exec(t):null},parse:function(){return{type:"tableSeparator"}},react:function(){return" | "},html:function(){return" | "}},autolink:{order:M++,match:s(/^<([^ >]+:\/[^ >]+)>/),parse:function(t,n,e){return{type:"link",content:[{type:"text",content:t[1]}],target:t[1]}},react:null,html:null},mailto:{order:M++,match:s(/^<([^ >]+@[^ >]+)>/),parse:function(t,n,e){var r=t[1],a=t[1];return X.test(a)||(a="mailto:"+a),{type:"link",content:[{type:"text",content:r}],target:a}},react:null,html:null},url:{order:M++,match:s(/^(https?:\/\/[^\s<]+[^<.,:;"')\]\s])/),parse:function(t,n,e){return{type:"link",content:[{type:"text",content:t[1]}],target:t[1],title:void 0}},react:null,html:null},link:{order:M++,match:s(new RegExp("^\\[("+z+")\\]\\("+G+"\\)")),parse:function(t,n,e){return{content:n(t[1],e),target:R(t[2]),title:t[3]}},react:function(t,n,e){return v("a",e.key,{href:w(t.target),title:t.title,children:n(t.content,e)})},html:function(t,n,e){var r={href:w(t.target),title:t.title};return k("a",n(t.content,e),r)}},image:{order:M++,match:s(new RegExp("^!\\[("+z+")\\]\\("+G+"\\)")),parse:function(t,n,e){return{alt:t[1],target:R(t[2]),title:t[3]}},react:function(t,n,e){return v("img",e.key,{src:w(t.target),alt:t.alt,title:t.title})},html:function(t,n,e){var r={src:w(t.target),alt:t.alt,title:t.title};return k("img","",r,!1)}},reflink:{order:M++,match:s(new RegExp("^\\[("+z+")\\]\\s*\\[([^\\]]*)\\]")),parse:function(t,n,e){return Z(t,e,{type:"link",content:n(t[1],e)})},react:null,html:null},refimage:{order:M++,match:s(new RegExp("^!\\[("+z+")\\]\\s*\\[([^\\]]*)\\]")),parse:function(t,n,e){return Z(t,e,{type:"image",alt:t[1]})},react:null,html:null},em:{order:M,match:s(new RegExp("^\\b_((?:__|\\\\[\\s\\S]|[^\\\\_])+?)_\\b|^\\*(?=\\S)((?:\\*\\*|\\\\[\\s\\S]|\\s+(?:\\\\[\\s\\S]|[^\\s\\*\\\\]|\\*\\*)|[^\\s\\*\\\\])+?)\\*(?!\\*)")),quality:function(t){return t[0].length+.2},parse:function(t,n,e){return{content:n(t[2]||t[1],e)}},react:function(t,n,e){return v("em",e.key,{children:n(t.content,e)})},html:function(t,n,e){return k("em",n(t.content,e))}},strong:{order:M,match:s(/^\*\*((?:\\[\s\S]|[^\\])+?)\*\*(?!\*)/),quality:function(t){return t[0].length+.1},parse:O,react:function(t,n,e){return v("strong",e.key,{children:n(t.content,e)})},html:function(t,n,e){return k("strong",n(t.content,e))}},u:{order:M++,match:s(/^__((?:\\[\s\S]|[^\\])+?)__(?!_)/),quality:function(t){return t[0].length},parse:O,react:function(t,n,e){return v("u",e.key,{children:n(t.content,e)})},html:function(t,n,e){return k("u",n(t.content,e))}},del:{order:M++,match:s(/^~~(?=\S)((?:\\[\s\S]|~(?!~)|[^\s\\~]|\s+(?!~~))+?)~~/),parse:O,react:function(t,n,e){return v("del",e.key,{children:n(t.content,e)})},html:function(t,n,e){return k("del",n(t.content,e))}},inlineCode:{order:M++,match:s(/^(`+)\s*([\s\S]*?[^`])\s*\1(?!`)/),parse:function(t,n,e){return{content:t[2]}},react:function(t,n,e){return v("code",e.key,{children:t.content})},html:function(t,n,e){return k("code",E(t.content))}},br:{order:M++,match:y(/^ {2,}\n/),parse:T,react:function(t,n,e){return v("br",e.key,x)},html:function(t,n,e){return"<br>"}},text:{order:M++,match:y(/^[\s\S]+?(?=[^0-9A-Za-z\s\u00c0-\uffff]|\n\n| {2,}\n|\w+:\S|$)/),parse:function(t,n,e){return{content:t[0]}},react:function(t,n,e){return t.content},html:function(t,n,e){return E(t.content)}}},H=function(e,r,a){if(!r)throw new Error("simple-markdown: outputFor: `property` must be defined. if you just upgraded, you probably need to replace `outputFor` with `reactFor`");var l,o=e.Array||U.Array,u=function(t,n){return l=n=n||l,Array.isArray(t)?o[r](t,u,n):e[t.type][r](t,u,n)};return function(t,n){return l=i(n,a),u(t,l)}},D=f(U),Q=function(t,n){return(n=n||{}).inline=!1,D(t,n)},J=function(t,n){var e=B.test(t);return(n=n||{}).inline=!e,D(t,n)},K=H(U,"react"),V=H(U,"html"),W=function(t,n){return K(Q(t,n),n)},Y={defaultRules:U,parserFor:f,outputFor:H,inlineRegex:s,blockRegex:m,anyScopeRegex:y,parseInline:A,parseBlock:function(t,n,e){var r=e.inline||!1;e.inline=!1;var a=t(n+"\n\n",e);return e.inline=r,a},markdownToReact:W,markdownToHtml:function(t,n){return V(Q(t,n),n)},ReactMarkdown:function(t){var n={};for(var e in t)"source"!==e&&Object.prototype.hasOwnProperty.call(t,e)&&(n[e]=t[e]);return n.children=W(t.source),v("div",null,n)},defaultBlockParse:Q,defaultInlineParse:function(t,n){return(n=n||{}).inline=!0,D(t,n)},defaultImplicitParse:J,defaultReactOutput:K,defaultHtmlOutput:V,preprocess:c,sanitizeText:E,sanitizeUrl:w,unescapeUrl:R,htmlTag:k,reactElement:v,defaultRawParse:D,ruleOutput:function(r,a){return a||"undefined"==typeof console||console.warn("simple-markdown ruleOutput should take 'react' or 'html' as the second argument."),function(t,n,e){return r[t.type][a](t,n,e)}},reactFor:function(u){var c=function(t,n){if(n=n||{},Array.isArray(t)){for(var e=n.key,r=[],a=null,l=0;l<t.length;l++){n.key=""+l;var o=c(t[l],n);"string"==typeof o&&"string"==typeof a?(a+=o,r[r.length-1]=a):(r.push(o),a=o)}return n.key=e,r}return u(t,c,n)};return c},htmlFor:function(e){var r=function(t,n){return n=n||{},Array.isArray(t)?t.map(function(t){return r(t,n)}).join(""):e(t,r,n)};return r},defaultParse:function(){return"undefined"!=typeof console&&console.warn("defaultParse is deprecated, please use `defaultImplicitParse`"),J.apply(null,arguments)},defaultOutput:function(){return"undefined"!=typeof console&&console.warn("defaultOutput is deprecated, please use `defaultReactOutput`"),K.apply(null,arguments)}};"undefined"!=typeof module&&module.exports?module.exports=Y:"undefined"!=typeof global?global.SimpleMarkdown=Y:window.SimpleMarkdown=Y}(); \ No newline at end of file +!function(){var p,u,n,e,r,d,h,t,a=/\r\n?/g,l=/\t/g,o=/\f/g,c=function(t){return t.replace(a,"\n").replace(o,"").replace(l," ")},i=function(t,n){var e=t||{};if(null!=n)for(var r in n)Object.prototype.hasOwnProperty.call(n,r)&&(e[r]=n[r]);return e},f=function(m,e){var y,g=Object.keys(m).filter(function(t){var n=m[t];if(null==n||null==n.match)return!1;var e=n.order;return"number"==typeof e&&isFinite(e)||"undefined"==typeof console||console.warn("simple-markdown: Invalid order for rule `"+t+"`: "+String(e)),!0});g.sort(function(t,n){var e=m[t],r=m[n],a=e.order,l=r.order;if(a!==l)return a-l;var o=e.quality?0:1,u=r.quality?0:1;return o!==u?o-u:t<n?-1:n<t?1:0});var v=function(t,n){var e=[];y=n=n||y;for(var r="";t;){var a=null,l=null,o=null,u=NaN,c=0,i=g[0],f=m[i];do{var s=f.order,p=f.match(t,n,r);if(p){var d=f.quality?f.quality(p,n,r):0;d<=u||(a=i,l=f,o=p,u=d)}i=g[++c],f=m[i]}while(f&&(!o||f.order===s&&f.quality));if(!0!==n.disableErrorGuards){if(null==l||null==o)throw new Error("Could not find a matching rule for the below content. The rule with highest `order` should always match content provided to it. Check the definition of `match` for '"+g[g.length-1]+"'. It seems to not match the following source:\n"+t);if(0!==o.index&&t.slice(0,o[0].length)!==o[0])throw new Error("`match` must return a capture starting at index 0 (the current parse index). Did you forget a ^ at the start of the RegExp?")}var h=l.parse(o,v,n);Array.isArray(h)?Array.prototype.push.apply(e,h):(null==h.type&&(h.type=a),e.push(h)),r=o[0],t=t.substring(r.length)}return e};return function(t,n){return(y=i(n,e)).inline||y.disableAutoBlockNewlines||(t+="\n\n"),v(c(t),y)}},s=function(e){var t=function(t,n){return n.inline?e.exec(t):null};return t.regex=e,t},m=function(e){var t=function(t,n){return n.inline?null:e.exec(t)};return t.regex=e,t},y=function(e){var t=function(t,n){return e.exec(t)};return t.regex=e,t},g="function"==typeof Symbol&&Symbol.for&&Symbol.for("react.element")||60103,v=function(t,n,e){return{$$typeof:g,type:t,key:n,ref:null,props:e,_owner:null}},k=function(t,n,e,r){e=e||{},r=void 0===r||r;var a="";for(var l in e){var o=e[l];Object.prototype.hasOwnProperty.call(e,l)&&o&&(a+=" "+E(l)+'="'+E(o)+'"')}var u="<"+t+a+">";return r?u+n+"</"+t+">":u},x={},w=function(t){if(null==t)return null;try{var n=decodeURIComponent(t).replace(/[^A-Za-z0-9/:]/g,"").toLowerCase();if(0===n.indexOf("javascript:")||0===n.indexOf("vbscript:")||0===n.indexOf("data:"))return null}catch(t){return null}return t},b=/[<>&"']/g,_={"<":"<",">":">","&":"&",'"':""","'":"'","/":"/","`":"`"},E=function(t){return String(t).replace(b,function(t){return _[t]})},S=/\\([^0-9A-Za-z\s])/g,R=function(t){return t.replace(S,"$1")},A=function(t,n,e){var r=e.inline||!1;e.inline=!0;var a=t(n,e);return e.inline=r,a},$=function(t,n,e){return{content:A(n,t[1],e)}},O=function(){return{}},T="(?:[*+-]|\\d+\\.)",P="( *)("+T+") +",j=new RegExp("^"+P),q=new RegExp(P+"[^\\n]*(?:\\n(?!\\1"+T+" )[^\\n]*)*(\n|$)","gm"),B=/\n{2,}$/,F=/^ ( *` *) $|^ ( *`)|(` *) $/g,N=B,C=/ *\n+$/,I=new RegExp("^( *)("+T+") [\\s\\S]+?(?:\n{2,}(?! )(?!\\1"+T+" )\\n*|\\s*\n*$)"),L=/(?:^|\n)( *)$/,z=(p=/^ *\| *| *\| *$/g,u=/ *$/,n=/^ *-+: *$/,e=/^ *:-+: *$/,r=/^ *:-+ *$/,d=function(t){return n.test(t)?"right":e.test(t)?"center":r.test(t)?"left":null},h=function(t,n,e,r){var a=e.inTable;e.inTable=!0;var l=n(t.trim(),e);e.inTable=a;var o=[[]];return l.forEach(function(t,n){"tableSeparator"===t.type?(!r||0!==n&&n!==l.length-1)&&o.push([]):("text"!==t.type||null!=l[n+1]&&"tableSeparator"!==l[n+1].type||(t.content=t.content.replace(u,"")),o[o.length-1].push(t))}),o},{parseTable:(t=function(s){return function(t,n,e){e.inline=!0;var r,a,l,o,u,c=h(t[1],n,e,s),i=(r=t[2],s&&(r=r.replace(p,"")),r.trim().split("|").map(d)),f=(a=t[3],l=n,o=e,u=s,a.trim().split("\n").map(function(t){return h(t,l,o,u)}));return e.inline=!1,{type:"table",header:c,align:i,cells:f}}})(!0),parseNpTable:t(!1),TABLE_REGEX:/^ *(\|.+)\n *\|( *[-:]+[-| :]*)\n((?: *\|.*(?:\n|$))*)\n*/,NPTABLE_REGEX:/^ *(\S.*\|.*)\n *([-:]+ *\|[-| :]*)\n((?:.*\|.*(?:\n|$))*)\n*/}),G="(?:\\[[^\\]]*\\]|[^\\[\\]]|\\](?=[^\\[]*\\]))*",X="\\s*<?((?:[^\\s\\\\]|\\\\.)*?)>?(?:\\s+['\"]([\\s\\S]*?)['\"])?\\s*",Z=/mailto:/i,M=function(t,n,e){var r=(t[2]||t[1]).replace(/\s+/g," ").toLowerCase();if(n._defs&&n._defs[r]){var a=n._defs[r];e.target=a.target,e.title=a.title}return n._refs=n._refs||{},n._refs[r]=n._refs[r]||[],n._refs[r].push(e),e},U=0,H={Array:{react:function(t,n,e){for(var r=e.key,a=[],l=0,o=0;l<t.length;l++,o++){e.key=""+l;var u=t[l];if("text"===u.type)for(u={type:"text",content:u.content};l+1<t.length&&"text"===t[l+1].type;l++)u.content+=t[l+1].content;a.push(n(u,e))}return e.key=r,a},html:function(t,n,e){for(var r="",a=0;a<t.length;a++){var l=t[a];if("text"===l.type)for(l={type:"text",content:l.content};a+1<t.length&&"text"===t[a+1].type;a++)l.content+=t[a+1].content;r+=n(l,e)}return r}},heading:{order:U++,match:m(/^ *(#{1,6})([^\n]+?)#* *(?:\n *)+\n/),parse:function(t,n,e){return{level:t[1].length,content:A(n,t[2].trim(),e)}},react:function(t,n,e){return v("h"+t.level,e.key,{children:n(t.content,e)})},html:function(t,n,e){return k("h"+t.level,n(t.content,e))}},nptable:{order:U++,match:m(z.NPTABLE_REGEX),parse:z.parseNpTable,react:null,html:null},lheading:{order:U++,match:m(/^([^\n]+)\n *(=|-){3,} *(?:\n *)+\n/),parse:function(t,n,e){return{type:"heading",level:"="===t[2]?1:2,content:A(n,t[1],e)}},react:null,html:null},hr:{order:U++,match:m(/^( *[-*_]){3,} *(?:\n *)+\n/),parse:O,react:function(t,n,e){return v("hr",e.key,x)},html:function(t,n,e){return"<hr>"}},codeBlock:{order:U++,match:m(/^(?: [^\n]+\n*)+(?:\n *)+\n/),parse:function(t,n,e){return{lang:void 0,content:t[0].replace(/^ /gm,"").replace(/\n+$/,"")}},react:function(t,n,e){var r=t.lang?"markdown-code-"+t.lang:void 0;return v("pre",e.key,{children:v("code",null,{className:r,children:t.content})})},html:function(t,n,e){var r=t.lang?"markdown-code-"+t.lang:void 0,a=k("code",E(t.content),{class:r});return k("pre",a)}},fence:{order:U++,match:m(/^ *(`{3,}|~{3,}) *(?:(\S+) *)?\n([\s\S]+?)\n?\1 *(?:\n *)+\n/),parse:function(t,n,e){return{type:"codeBlock",lang:t[2]||void 0,content:t[3]}},react:null,html:null},blockQuote:{order:U++,match:m(/^( *>[^\n]+(\n[^\n]+)*\n*)+\n{2,}/),parse:function(t,n,e){return{content:n(t[0].replace(/^ *> ?/gm,""),e)}},react:function(t,n,e){return v("blockquote",e.key,{children:n(t.content,e)})},html:function(t,n,e){return k("blockquote",n(t.content,e))}},list:{order:U++,match:function(t,n,e){var r=L.exec(e),a=n._list||!n.inline;return r&&a?(t=r[1]+t,I.exec(t),I.exec(t)):null},parse:function(t,p,d){var n=t[2],e=1<n.length,r=e?+n:void 0,h=t[0].replace(N,"\n").match(q),m=!1;return{ordered:e,start:r,items:h.map(function(t,n){var e=j.exec(t),r=e?e[0].length:0,a=new RegExp("^ {1,"+r+"}","gm"),l=t.replace(a,"").replace(j,""),o=n===h.length-1,u=-1!==l.indexOf("\n\n")||o&&m;m=u;var c,i=d.inline,f=d._list;d._list=!0,c=u?(d.inline=!1,l.replace(C,"\n\n")):(d.inline=!0,l.replace(C,""));var s=p(c,d);return d.inline=i,d._list=f,s})}},react:function(t,e,r){var n=t.ordered?"ol":"ul";return v(n,r.key,{start:t.start,children:t.items.map(function(t,n){return v("li",""+n,{children:e(t,r)})})})},html:function(t,n,e){var r=t.items.map(function(t){return k("li",n(t,e))}).join(""),a=t.ordered?"ol":"ul",l={start:t.start};return k(a,r,l)}},def:{order:U++,match:m(/^ *\[([^\]]+)\]: *<?([^\s>]*)>?(?: +["(]([^\n]+)[")])? *\n(?: *\n)*/),parse:function(t,n,e){var r=t[1].replace(/\s+/g," ").toLowerCase(),a=t[2],l=t[3];return e._refs&&e._refs[r]&&e._refs[r].forEach(function(t){t.target=a,t.title=l}),e._defs=e._defs||{},e._defs[r]={target:a,title:l},{def:r,target:a,title:l}},react:function(){return null},html:function(){return""}},table:{order:U++,match:m(z.TABLE_REGEX),parse:z.parseTable,react:function(n,e,r){var a=function(t){return null==n.align[t]?{}:{textAlign:n.align[t]}},t=n.header.map(function(t,n){return v("th",""+n,{style:a(n),scope:"col",children:e(t,r)})}),l=n.cells.map(function(t,n){return v("tr",""+n,{children:t.map(function(t,n){return v("td",""+n,{style:a(n),children:e(t,r)})})})});return v("table",r.key,{children:[v("thead","thead",{children:v("tr",null,{children:t})}),v("tbody","tbody",{children:l})]})},html:function(n,e,r){var a=function(t){return null==n.align[t]?"":"text-align:"+n.align[t]+";"},t=n.header.map(function(t,n){return k("th",e(t,r),{style:a(n),scope:"col"})}).join(""),l=n.cells.map(function(t){var n=t.map(function(t,n){return k("td",e(t,r),{style:a(n)})}).join("");return k("tr",n)}).join(""),o=k("thead",k("tr",t)),u=k("tbody",l);return k("table",o+u)}},newline:{order:U++,match:m(/^(?:\n *)*\n/),parse:O,react:function(t,n,e){return"\n"},html:function(t,n,e){return"\n"}},paragraph:{order:U++,match:m(/^((?:[^\n]|\n(?! *\n))+)(?:\n *)+\n/),parse:$,react:function(t,n,e){return v("div",e.key,{className:"paragraph",children:n(t.content,e)})},html:function(t,n,e){return k("div",n(t.content,e),{class:"paragraph"})}},escape:{order:U++,match:s(/^\\([^0-9A-Za-z\s])/),parse:function(t,n,e){return{type:"text",content:t[1]}},react:null,html:null},tableSeparator:{order:U++,match:function(t,n){return n.inTable?/^ *\| */.exec(t):null},parse:function(){return{type:"tableSeparator"}},react:function(){return" | "},html:function(){return" | "}},autolink:{order:U++,match:s(/^<([^ >]+:\/[^ >]+)>/),parse:function(t,n,e){return{type:"link",content:[{type:"text",content:t[1]}],target:t[1]}},react:null,html:null},mailto:{order:U++,match:s(/^<([^ >]+@[^ >]+)>/),parse:function(t,n,e){var r=t[1],a=t[1];return Z.test(a)||(a="mailto:"+a),{type:"link",content:[{type:"text",content:r}],target:a}},react:null,html:null},url:{order:U++,match:s(/^(https?:\/\/[^\s<]+[^<.,:;"')\]\s])/),parse:function(t,n,e){return{type:"link",content:[{type:"text",content:t[1]}],target:t[1],title:void 0}},react:null,html:null},link:{order:U++,match:s(new RegExp("^\\[("+G+")\\]\\("+X+"\\)")),parse:function(t,n,e){return{content:n(t[1],e),target:R(t[2]),title:t[3]}},react:function(t,n,e){return v("a",e.key,{href:w(t.target),title:t.title,children:n(t.content,e)})},html:function(t,n,e){var r={href:w(t.target),title:t.title};return k("a",n(t.content,e),r)}},image:{order:U++,match:s(new RegExp("^!\\[("+G+")\\]\\("+X+"\\)")),parse:function(t,n,e){return{alt:t[1],target:R(t[2]),title:t[3]}},react:function(t,n,e){return v("img",e.key,{src:w(t.target),alt:t.alt,title:t.title})},html:function(t,n,e){var r={src:w(t.target),alt:t.alt,title:t.title};return k("img","",r,!1)}},reflink:{order:U++,match:s(new RegExp("^\\[("+G+")\\]\\s*\\[([^\\]]*)\\]")),parse:function(t,n,e){return M(t,e,{type:"link",content:n(t[1],e)})},react:null,html:null},refimage:{order:U++,match:s(new RegExp("^!\\[("+G+")\\]\\s*\\[([^\\]]*)\\]")),parse:function(t,n,e){return M(t,e,{type:"image",alt:t[1]})},react:null,html:null},em:{order:U,match:s(new RegExp("^\\b_((?:__|\\\\[\\s\\S]|[^\\\\_])+?)_\\b|^\\*(?=\\S)((?:\\*\\*|\\\\[\\s\\S]|\\s+(?:\\\\[\\s\\S]|[^\\s\\*\\\\]|\\*\\*)|[^\\s\\*\\\\])+?)\\*(?!\\*)")),quality:function(t){return t[0].length+.2},parse:function(t,n,e){return{content:n(t[2]||t[1],e)}},react:function(t,n,e){return v("em",e.key,{children:n(t.content,e)})},html:function(t,n,e){return k("em",n(t.content,e))}},strong:{order:U,match:s(/^\*\*((?:\\[\s\S]|[^\\])+?)\*\*(?!\*)/),quality:function(t){return t[0].length+.1},parse:$,react:function(t,n,e){return v("strong",e.key,{children:n(t.content,e)})},html:function(t,n,e){return k("strong",n(t.content,e))}},u:{order:U++,match:s(/^__((?:\\[\s\S]|[^\\])+?)__(?!_)/),quality:function(t){return t[0].length},parse:$,react:function(t,n,e){return v("u",e.key,{children:n(t.content,e)})},html:function(t,n,e){return k("u",n(t.content,e))}},del:{order:U++,match:s(/^~~(?=\S)((?:\\[\s\S]|~(?!~)|[^\s~]|\s(?!~~))+?)~~/),parse:$,react:function(t,n,e){return v("del",e.key,{children:n(t.content,e)})},html:function(t,n,e){return k("del",n(t.content,e))}},inlineCode:{order:U++,match:s(/^(`+)([\s\S]*?[^`])\1(?!`)/),parse:function(t,n,e){return{content:t[2].replace(F,"$1")}},react:function(t,n,e){return v("code",e.key,{children:t.content})},html:function(t,n,e){return k("code",E(t.content))}},br:{order:U++,match:y(/^ {2,}\n/),parse:O,react:function(t,n,e){return v("br",e.key,x)},html:function(t,n,e){return"<br>"}},text:{order:U++,match:y(/^[\s\S]+?(?=[^0-9A-Za-z\s\u00c0-\uffff]|\n\n| {2,}\n|\w+:\S|$)/),parse:function(t,n,e){return{content:t[0]}},react:function(t,n,e){return t.content},html:function(t,n,e){return E(t.content)}}},D=function(e,r,a){if(!r)throw new Error("simple-markdown: outputFor: `property` must be defined. if you just upgraded, you probably need to replace `outputFor` with `reactFor`");var l,o=e.Array||H.Array,u=function(t,n){return l=n=n||l,Array.isArray(t)?o[r](t,u,n):e[t.type][r](t,u,n)};return function(t,n){return l=i(n,a),u(t,l)}},Q=f(H),J=function(t,n){return(n=n||{}).inline=!1,Q(t,n)},K=function(t,n){var e=B.test(t);return(n=n||{}).inline=!e,Q(t,n)},V=D(H,"react"),W=D(H,"html"),Y=function(t,n){return V(J(t,n),n)},tt={defaultRules:H,parserFor:f,outputFor:D,inlineRegex:s,blockRegex:m,anyScopeRegex:y,parseInline:A,parseBlock:function(t,n,e){var r=e.inline||!1;e.inline=!1;var a=t(n+"\n\n",e);return e.inline=r,a},markdownToReact:Y,markdownToHtml:function(t,n){return W(J(t,n),n)},ReactMarkdown:function(t){var n={};for(var e in t)"source"!==e&&Object.prototype.hasOwnProperty.call(t,e)&&(n[e]=t[e]);return n.children=Y(t.source),v("div",null,n)},defaultBlockParse:J,defaultInlineParse:function(t,n){return(n=n||{}).inline=!0,Q(t,n)},defaultImplicitParse:K,defaultReactOutput:V,defaultHtmlOutput:W,preprocess:c,sanitizeText:E,sanitizeUrl:w,unescapeUrl:R,htmlTag:k,reactElement:v,defaultRawParse:Q,ruleOutput:function(r,a){return a||"undefined"==typeof console||console.warn("simple-markdown ruleOutput should take 'react' or 'html' as the second argument."),function(t,n,e){return r[t.type][a](t,n,e)}},reactFor:function(u){var c=function(t,n){if(n=n||{},Array.isArray(t)){for(var e=n.key,r=[],a=null,l=0;l<t.length;l++){n.key=""+l;var o=c(t[l],n);"string"==typeof o&&"string"==typeof a?(a+=o,r[r.length-1]=a):(r.push(o),a=o)}return n.key=e,r}return u(t,c,n)};return c},htmlFor:function(e){var r=function(t,n){return n=n||{},Array.isArray(t)?t.map(function(t){return r(t,n)}).join(""):e(t,r,n)};return r},defaultParse:function(){return"undefined"!=typeof console&&console.warn("defaultParse is deprecated, please use `defaultImplicitParse`"),K.apply(null,arguments)},defaultOutput:function(){return"undefined"!=typeof console&&console.warn("defaultOutput is deprecated, please use `defaultReactOutput`"),V.apply(null,arguments)}};"undefined"!=typeof module&&module.exports?module.exports=tt:"undefined"!=typeof global?global.SimpleMarkdown=tt:window.SimpleMarkdown=tt}(); \ No newline at end of file
89797fef9abbinlineCode: Fix ReDoS & improve escape semantics
2 files changed · +23 −2
simple-markdown.js+3 −2 modified@@ -640,6 +640,7 @@ var LIST_ITEM_R = new RegExp( "gm" ); var BLOCK_END_R = /\n{2,}$/; +var INLINE_CODE_ESCAPE_BACKTICKS_R = /^ ( *` *) $|^ ( *`)|(` *) $/g; // recognize the end of a paragraph block inside a list item: // two or more newlines at end end of the item var LIST_BLOCK_END_R = BLOCK_END_R; @@ -1581,10 +1582,10 @@ var defaultRules /* : DefaultRules */ = { }, inlineCode: { order: currOrder++, - match: inlineRegex(/^(`+)\s*([\s\S]*?[^`])\s*\1(?!`)/), + match: inlineRegex(/^(`+)([\s\S]*?[^`])\1(?!`)/), parse: function(capture, parse, state) { return { - content: capture[2] + content: capture[2].replace(INLINE_CODE_ESCAPE_BACKTICKS_R, "$1") }; }, react: function(node, output, state) {
__tests__/simple-markdown-test.js+20 −0 modified@@ -550,6 +550,26 @@ describe("simple markdown", function() { }]); }); + it("should ignore a single space at the start and end of an inline code block separating a '`'", function() { + var parsed1 = inlineParse( + "test `` ` `` escaping a code block" + ); + validateParse(parsed1, [ + {type: "text", content: "test "}, + {type: "inlineCode", content: "`"}, + {type: "text", content: " escaping a code block"}, + ]); + + var parsed1 = inlineParse( + "test `` ` `` escaping a code block" + ); + validateParse(parsed1, [ + {type: "text", content: "test "}, + {type: "inlineCode", content: " ` "}, + {type: "text", content: " escaping a code block"}, + ]); + }); + it("should allow you to escape special characters with \\", function() { var parsed = inlineParse( "\\`hi\\` \\*bye\\* \\~\\|\\<\\[\\{"
Vulnerability mechanics
Generated on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
8- github.com/ariabuckles/simple-markdown/commit/89797fef9abb4cab2fb76a335968266a92588816ghsapatchWEB
- github.com/ariabuckles/simple-markdown/releases/tag/0.5.2ghsapatchWEB
- github.com/advisories/GHSA-gpvj-gp8c-c7p2ghsaADVISORY
- nvd.nist.gov/vuln/detail/CVE-2019-25103ghsaADVISORY
- github.com/Khan/simple-markdown/issues/71ghsaWEB
- snyk.io/vuln/SNYK-JS-SIMPLEMARKDOWN-460540ghsaWEB
- vuldb.comghsasignaturepermissions-requiredWEB
- vuldb.comghsavdb-entrytechnical-descriptionWEB
News mentions
0No linked articles in our index yet.