{"id":"CVE-2026-41680","aliases":["GHSA-6v9c-7cg6-27q7"],"url":"https://o3.security/vulnerability/CVE-2026-41680","summary":"Marked: OOM Denial of Service via Infinite Recursion in marked Tokenizer","details":"### Summary\nA critical Denial of Service (DoS) vulnerability exists in `marked@18.0.0`. By providing a specific 3-byte input sequence a tab, a vertical tab, and a newline (`\\x09\\x0b\\n`)—an unauthenticated attacker can trigger an infinite recursion loop during parsing. This leads to unbounded memory allocation, causing the host Node.js application to crash via Memory Exhaustion (OOM). \n\n### Details\nThe vulnerability originates in how `marked`'s block tokenizer handles unexpected whitespace characters. \n\n1. **Tab Character (`\\x09`) Consumption**: The `space()` tokenizer matches standard whitespace using the regex `/^(?:[ \\t]*(?:\\n|$))+/`. When parsing the malicious payload (`\\x09\\x0b\\n`), this rule successfully consumes the initial tab character (`\\x09`).\n2. **Vertical Tab (`\\x0b`) Bypass**: The remaining input is now `\\x0b\\n`. The newline block rule explicitly looks for spaces or standard tabs (`[ \\t]`) followed by a newline. Because the vertical tab is a legacy ASCII character not accounted for in this rule, it fails to match.\n3. **Fallback to Text Tokenizer**: None of the standard block tokenizers (blockquote, code, heading, etc.) match `\\x0b\\n`. As a result, the parser falls through to the `text` tokenizer (`/^[^\\n]+/`), which matches any character except a newline.\n4. **Infinite Recursion**: Inside `blockTokens()`, the `text` tokenizer creates a text token and subsequently calls `inlineTokens()` on the exact same content. Inside `inlineTokens()`, the text rule again matches `\\x0b\\n` and recursively calls `inlineTokens()`. This creates an inescapable cycle: `blockTokens() → text token → inlineTokens() → text rule matches → inlineTokens() → ...`\n\nWith each recursive call allocating new token objects and concatenating strings, memory grows indefinitely until the Node.js heap limit is reached.\n\n**Vulnerable Code in `lib/marked.esm.js` (Lexer class, `blockTokens()`):**\n```javascript\n// The text tokenizer triggers infinite recursion\nif(r=this.tokenizer.text(e)) {\n    e=e.substring(r.raw.length);\n    let s=t.at(-1);\n    s?.type===\"text\"?(s.raw+=(s.raw.endsWith(\"\\n\")?\"\":\"\\n\")+r.raw, s.text+=\"\\n\"+r.text, this.inlineQueue.pop(), this.inlineQueue.at(-1).src=s.text):t.push(r);\n    // ↑ This calls inlineTokens() internally via the text tokenizer, causing the OOM loop\n    continue;\n}\n```\n\n### PoC\nThis vulnerability can be reproduced using any standard Node.js environment with `marked@18.0.0` installed.\n\n1. Create a file named `poc.js` with the following content:\n```javascript\nconst marked = require('marked');\n\n// The vulnerable 3-byte pattern: tab + vertical tab + newline\nconst vulnerableInput = '\\x09\\x0b\\n';\n\nconsole.log('Attempting to parse malicious payload...');\ntry {\n    marked.parse(vulnerableInput);\n} catch(e) {\n    console.log('Error:', e.message);\n}\n```\n2. Run the script: `node poc.js`\n3. **Result:** The process will hang briefly as memory spikes, ultimately crashing with: `FATAL ERROR: Reached heap limit Allocation failed - JavaScript heap out of memory`.\n\n### Impact\nThis is a High-Severity Denial of Service (DoS) vulnerability via Memory Exhaustion. \n\n**Impacted Parties:** Any application, API, chatbot, or documentation system using `marked@18.0.0` (and potentially earlier versions) to parse untrusted user input is vulnerable. \n\nBecause the payload requires zero authentication and only 3 bytes of data, it requires virtually no resources from the attacker to remotely crash the service and achieve a total loss of availability for the targeted application.","published":"2026-04-24T17:26:27.847Z","modified":"2026-08-12T03:51:41.882976433Z","cvss":null,"epss":{"score":0.00342,"percentile":0.27054,"asOf":"2026-08-13"},"cisaKev":null,"exploitsKnown":0,"affectedPackages":[{"ecosystem":"npm","name":"marked","fixedVersion":"18.0.2"}],"fix":null,"references":[{"type":"ADVISORY","url":"https://github.com/CVEProject/cvelistV5/tree/main/cves/2026/41xxx/CVE-2026-41680.json"},{"type":"ADVISORY","url":"https://github.com/markedjs/marked/security/advisories/GHSA-6v9c-7cg6-27q7"},{"type":"ADVISORY","url":"https://nvd.nist.gov/vuln/detail/CVE-2026-41680"},{"type":"PACKAGE","url":"https://github.com/markedjs/marked"}],"provenance":{"sources":["OSV.dev","FIRST.org (EPSS)"],"lastVerified":"2026-08-12T03:51:41.882976433Z"}}