{"description":"Trending threats, MITRE ATT\u0026CK coverage, and detection metadata. Fed continuously.","favicon":"https://feed.craftedsignal.io/favicon-32x32.png","feed_url":"https://feed.craftedsignal.io/products/commonmark--2.0.0--2.10.1/feed.json","home_page_url":"https://feed.craftedsignal.io/","icon":"https://feed.craftedsignal.io/apple-touch-icon.png","items":[{"_cs_actors":[],"_cs_cpes":[],"_cs_cves":[],"_cs_exploited":false,"_cs_has_poc":false,"_cs_poc_references":[],"_cs_products":["commonmark (\u003e= 2.0.0, \u003c= 2.10.1)"],"_cs_severities":["medium"],"_cs_tags":[],"_cs_type":"advisory","_cs_vendors":["thephpleague"],"content_html":"\u003cp\u003eThe \u003ccode\u003eleague/commonmark\u003c/code\u003e library, specifically in versions 2.0.0 through 2.10.1, contains a quadratic-time complexity vulnerability in its GitHub Flavored Markdown (GFM) Table extension. The \u003ccode\u003eTableStartParser\u003c/code\u003e performs a full-buffer scan of the accumulated paragraph on every new line via \u003ccode\u003estrpos()\u003c/code\u003e to check for potential table headers. Because the paragraph buffer grows indefinitely as long as non-blank lines are provided, and the scan traverses this entire buffer repeatedly, the work required grows quadratically (O(M^2)) relative to the input size. An unauthenticated attacker can exploit this by submitting large paragraphs consisting of lines that do not start with a letter (bypassing the \u003ccode\u003eSkipLinesStartingWithLettersParser\u003c/code\u003e) and contain no pipe characters. This causes excessive CPU usage, which can exhaust available PHP worker processes and result in a denial of service.\u003c/p\u003e\n\u003ch2 id=\"attack-chain\"\u003eAttack Chain\u003c/h2\u003e\n\u003col\u003e\n\u003cli\u003e\u003cstrong\u003eExposure:\u003c/strong\u003e The attacker identifies an application using \u003ccode\u003eleague/commonmark\u003c/code\u003e (specifically with \u003ccode\u003eGithubFlavoredMarkdownConverter\u003c/code\u003e or the \u003ccode\u003eTableExtension\u003c/code\u003e enabled) that processes untrusted Markdown content.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eControl:\u003c/strong\u003e The attacker prepares a large Markdown body consisting of a single paragraph with no blank lines, no pipe (\u003ccode\u003e|\u003c/code\u003e) characters, and lines beginning with non-letter characters (e.g., digits).\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003ePath:\u003c/strong\u003e As the parser processes the input, the \u003ccode\u003eParagraphParser\u003c/code\u003e keeps the paragraph block open, causing the library to append each line to the growing \u003ccode\u003eparagraph\u003c/code\u003e buffer.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eBypass:\u003c/strong\u003e Since the input lines do not begin with a letter, the \u003ccode\u003eSkipLinesStartingWithLettersParser\u003c/code\u003e returns \u003ccode\u003eBlockStart::abort()\u003c/code\u003e, allowing the parser to continue searching for other block types.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003ePrimitive:\u003c/strong\u003e The \u003ccode\u003eMarkdownParser\u003c/code\u003e dispatches the input to the \u003ccode\u003eTableStartParser::tryStart()\u003c/code\u003e on every line, which executes \u003ccode\u003estrpos($paragraph, '|')\u003c/code\u003e against the entire, continuously growing buffer.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eGuard Absence:\u003c/strong\u003e No input-size caps or effective length guards prevent the cumulative buffer growth or the exhaustive scan, allowing the O(M^2) complexity to manifest.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eResult:\u003c/strong\u003e The cumulative processing time leads to extreme CPU load, effectively exhausting server resources and denying service to legitimate users.\u003c/li\u003e\n\u003c/ol\u003e\n\u003ch2 id=\"impact\"\u003eImpact\u003c/h2\u003e\n\u003cp\u003eSuccessful exploitation results in a denial of service by consuming all available server resources or PHP worker threads. The impact is limited to availability, with no risk to data confidentiality or integrity. Applications rendering untrusted Markdown from external users are at the highest risk. Measured benchmarks demonstrate that doubling a multi-megabyte input quadruples the CPU time, with 200,000 lines taking approximately 27.81 seconds to parse.\u003c/p\u003e\n\u003ch2 id=\"recommendation\"\u003eRecommendation\u003c/h2\u003e\n\u003col\u003e\n\u003cli\u003eUpgrade \u003ccode\u003eleague/commonmark\u003c/code\u003e to a version where this vulnerability is remediated (as of this writing, no fix is available; monitor the upstream repository for updates).\u003c/li\u003e\n\u003cli\u003eImplement application-level constraints on the total length of user-submitted Markdown content before passing it to the converter.\u003c/li\u003e\n\u003cli\u003eIf not required, disable the \u003ccode\u003eTableExtension\u003c/code\u003e in the \u003ccode\u003eGithubFlavoredMarkdownConverter\u003c/code\u003e configuration when processing untrusted input.\u003c/li\u003e\n\u003cli\u003eMonitor application server CPU usage patterns specifically for PHP-FPM worker saturation coinciding with requests to Markdown rendering endpoints.\u003c/li\u003e\n\u003c/ol\u003e\n","date_modified":"2026-09-30T16:27:25Z","date_published":"2026-09-30T16:27:25Z","id":"https://feed.craftedsignal.io/briefs/2026-09-league-commonmark-dos/","summary":"An unauthenticated remote attacker can cause denial of service by submitting large Markdown paragraphs that trigger O(M^2) CPU consumption in the league/commonmark TableStartParser.","title":"Quadratic Time Denial of Service in league/commonmark Table Extension","url":"https://feed.craftedsignal.io/briefs/2026-09-league-commonmark-dos/"}],"language":"en","title":"CraftedSignal Threat Feed - Commonmark (\u003e= 2.0.0, \u003c= 2.10.1)","version":"https://jsonfeed.org/version/1.1"}