CVE-2026-41680: marked: infinite recursion DoS crashes Node.js via OOM
GHSA-6v9c-7cg6-27q7 HIGH PoC AVAILABLE CISA: TRACK*marked@18.0.0 contains an infinite recursion flaw in its block tokenizer that crashes any Node.js process with a 3-byte payload (tab + vertical tab + newline), requiring zero authentication and producing a fatal heap out-of-memory error. With 3,866 downstream npm dependents and a public PoC already available, every AI chatbot, agent UI, and documentation system that renders user-controlled markdown is a potential target—SSVC TRACK_STAR and EPSS top-75th-percentile exploitation probability confirm near-term opportunistic scanning is realistic. A single unauthenticated HTTP request is sufficient to crash an entire multi-tenant AI platform, making this a high-leverage denial-of-service primitive against LLM front-ends and RAG interfaces. Upgrade to marked@18.0.2 immediately; as an interim control, strip or reject vertical tab characters (\x0b) from all inputs before passing them to the parser.
What is the risk?
High severity with a trivially low exploitation barrier: the 3-byte payload requires no authentication, no AI/ML knowledge, and guarantees a hard crash of the Node.js host process. The high downstream dependent count (3,866 packages) multiplies exposure across the npm ecosystem, and the public PoC removes all research overhead for attackers. SSVC TRACK_STAR and EPSS top-75th percentile confirm this is a realistic near-term exploitation target. The OpenSSF Scorecard of 5.5/10 reflects modest supply-chain hygiene for a widely-deployed package. Not in CISA KEV, but the zero-auth crash-on-request profile makes active exploitation likely once automated scanners incorporate the signature.
How does the attack unfold?
What systems are affected?
| Package | Ecosystem | Vulnerable Range | Patched |
|---|---|---|---|
| Tokenizers | npm | >= 18.0.0, <= 18.0.1 | 18.0.2 |
Do you use Tokenizers? You're affected.
How severe is it?
What is the attack surface?
What should I do?
6 steps-
Upgrade to marked@18.0.2 immediately—the patch corrects the block tokenizer's handling of the vertical tab character (\x0b).
-
If immediate patching is blocked, add input sanitization to strip or reject \x0b (Unicode U+000B) before calling marked.parse().
-
Run npm audit or Dependabot to identify all transitive consumers of marked@18.0.0–18.0.1 across your supply chain.
-
Set Node.js --max-old-space-size limits and use a process manager (pm2, systemd) with auto-restart and exponential backoff to limit blast radius until patched.
-
Monitor application logs for sudden FATAL ERROR: JavaScript heap out of memory events as an indicator of active exploitation attempts.
-
If using a WAF, add a rule to detect or block requests containing raw vertical tab bytes (\x0b) in body or query parameters routed to markdown-processing endpoints.
What does CISA's SSVC say?
Source: CISA Vulnrichment (SSVC v2.0). Decision based on the CISA Coordinator decision tree.
How is it classified?
Which compliance frameworks are affected?
This CVE is relevant to:
Frequently Asked Questions
What is CVE-2026-41680?
marked@18.0.0 contains an infinite recursion flaw in its block tokenizer that crashes any Node.js process with a 3-byte payload (tab + vertical tab + newline), requiring zero authentication and producing a fatal heap out-of-memory error. With 3,866 downstream npm dependents and a public PoC already available, every AI chatbot, agent UI, and documentation system that renders user-controlled markdown is a potential target—SSVC TRACK_STAR and EPSS top-75th-percentile exploitation probability confirm near-term opportunistic scanning is realistic. A single unauthenticated HTTP request is sufficient to crash an entire multi-tenant AI platform, making this a high-leverage denial-of-service primitive against LLM front-ends and RAG interfaces. Upgrade to marked@18.0.2 immediately; as an interim control, strip or reject vertical tab characters (\x0b) from all inputs before passing them to the parser.
Is CVE-2026-41680 actively exploited?
Proof-of-concept exploit code is publicly available for CVE-2026-41680, increasing the risk of exploitation.
How to fix CVE-2026-41680?
1. Upgrade to marked@18.0.2 immediately—the patch corrects the block tokenizer's handling of the vertical tab character (\x0b). 2. If immediate patching is blocked, add input sanitization to strip or reject \x0b (Unicode U+000B) before calling marked.parse(). 3. Run npm audit or Dependabot to identify all transitive consumers of marked@18.0.0–18.0.1 across your supply chain. 4. Set Node.js --max-old-space-size limits and use a process manager (pm2, systemd) with auto-restart and exponential backoff to limit blast radius until patched. 5. Monitor application logs for sudden FATAL ERROR: JavaScript heap out of memory events as an indicator of active exploitation attempts. 6. If using a WAF, add a rule to detect or block requests containing raw vertical tab bytes (\x0b) in body or query parameters routed to markdown-processing endpoints.
What systems are affected by CVE-2026-41680?
This vulnerability affects the following AI/ML architecture patterns: LLM-powered chatbots, Agent framework UIs, RAG front-end interfaces, AI documentation generation systems, Model serving API gateways with markdown rendering.
What is the CVSS score for CVE-2026-41680?
CVE-2026-41680 has a CVSS v3.1 base score of 7.5 (HIGH). The EPSS exploitation probability is 0.34%.
What is the AI security impact?
Affected AI Architectures
MITRE ATLAS Techniques
AML.T0010.001 AI Software AML.T0029 Denial of AI Service AML.T0034.001 Resource-Intensive Queries AML.T0049 Exploit Public-Facing Application Compliance Controls Affected
What are the technical details?
Original Advisory
### Summary A 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). ### Details The vulnerability originates in how `marked`'s block tokenizer handles unexpected whitespace characters. 1. **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`). 2. **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. 3. **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. 4. **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() → ...` With each recursive call allocating new token objects and concatenating strings, memory grows indefinitely until the Node.js heap limit is reached. **Vulnerable Code in `lib/marked.esm.js` (Lexer class, `blockTokens()`):** ```javascript // The text tokenizer triggers infinite recursion if(r=this.tokenizer.text(e)) { e=e.substring(r.raw.length); let s=t.at(-1); 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); // ↑ This calls inlineTokens() internally via the text tokenizer, causing the OOM loop continue; } ``` ### PoC This vulnerability can be reproduced using any standard Node.js environment with `marked@18.0.0` installed. 1. Create a file named `poc.js` with the following content: ```javascript const marked = require('marked'); // The vulnerable 3-byte pattern: tab + vertical tab + newline const vulnerableInput = '\x09\x0b\n'; console.log('Attempting to parse malicious payload...'); try { marked.parse(vulnerableInput); } catch(e) { console.log('Error:', e.message); } ``` 2. Run the script: `node poc.js` 3. **Result:** The process will hang briefly as memory spikes, ultimately crashing with: `FATAL ERROR: Reached heap limit Allocation failed - JavaScript heap out of memory`. ### Impact This is a High-Severity Denial of Service (DoS) vulnerability via Memory Exhaustion. **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. Because 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.
Exploitation Scenario
An adversary targeting an AI-powered chatbot identifies that the application renders user-provided markdown—detectable via an exposed package.json in a public repository or by observing markdown-formatted LLM responses. They copy the 3-byte payload from the public GitHub advisory (\x09\x0b\n) and submit it as a chat message or API request body. The marked parser enters infinite recursion inside blockTokens(), allocating new token objects on each call; within seconds the Node.js heap limit is reached and the process crashes with FATAL ERROR: JavaScript heap out of memory. In a Kubernetes deployment the pod restarts in ~30 seconds, but the attacker re-submits the payload immediately, sustaining the outage indefinitely at essentially zero cost—3 bytes per crash, no rate-limit bypass required if the endpoint is public-facing.
Weaknesses (CWE)
CWE-400 Uncontrolled Resource Consumption
Primary
CWE-674 Uncontrolled Recursion
Primary
CWE-835 Loop with Unreachable Exit Condition ('Infinite Loop')
Primary
CWE-400 — Uncontrolled Resource Consumption: The product does not properly control the allocation and maintenance of a limited resource.
- [Architecture and Design] Design throttling mechanisms into the system architecture. The best protection is to limit the amount of resources that an unauthorized user can cause to be expended. A strong authentication and access control model will help prevent such attacks from occurring in the first place. The login application should be protected against DoS attacks as much as possible. Limiting the database access, perhaps by caching result sets, can help minimize the resources expended. To further limit the potential for a DoS attack, consider tracking the rate of requests received from users and blocking requests that exceed a defined rate threshold.
- [Architecture and Design] Mitigation of resource exhaustion attacks requires that the target system either: The first of these solutions is an issue in itself though, since it may allow attackers to prevent the use of the system by a particular valid user. If the attacker impersonates the valid user, they may be able to prevent the user from accessing the server in question. The second solution is simply difficult to effectively institute -- and even when properly done, it does not provide a full solution. It simply makes the attack require more resources on the part of the attacker. recognizes the attack and denies that user further access for a given amount of time, or uniformly throttles all requests in order to make it more difficult to consume resources more quickly than they can again be freed.
Source: MITRE CWE corpus.
CVSS Vector
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H References
Timeline
Related Vulnerabilities
CVE-2026-33660 10.0 TensorFlow: type confusion NPD in tensor conversion
Same attack type: DoS CVE-2023-25668 9.8 TensorFlow: unauthenticated RCE via heap buffer overflow
Same attack type: DoS CVE-2022-23587 9.8 TensorFlow: integer overflow in Grappler enables RCE
Same attack type: DoS CVE-2022-35939 9.8 TensorFlow: ScatterNd OOB write enables RCE/crash
Same attack type: DoS CVE-2022-41900 9.8 TensorFlow: heap OOB RCE in FractionalMaxPool op
Same attack type: DoS