CVE-2026-41680: marked: infinite recursion DoS crashes Node.js via OOM

GHSA-6v9c-7cg6-27q7 HIGH PoC AVAILABLE CISA: TRACK*
Published April 29, 2026
CISO Take

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.

Sources: NVD GitHub Advisory EPSS ATLAS OpenSSF

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?

Target Discovery
Adversary identifies AI applications using marked@18.0.0–18.0.1 by scanning public package.json files, npm dependency graphs, or GitHub repository searches for the vulnerable version string.
AML.T0004
Payload Acquisition
Adversary copies the 3-byte PoC payload (\x09\x0b\n) directly from the public GitHub security advisory—zero development effort or AI knowledge required.
AML.T0016.001
Exploitation
Adversary submits the payload via any unauthenticated endpoint that passes input to marked.parse(), triggering infinite recursion in the block tokenizer and initiating unbounded heap memory growth.
AML.T0049
Service Disruption
Node.js process exhausts the heap limit and crashes with a fatal OOM error, rendering the AI application completely unavailable to all users until manual or automated process restart.
AML.T0029

What systems are affected?

Package Ecosystem Vulnerable Range Patched
Tokenizers npm >= 18.0.0, <= 18.0.1 18.0.2
10.8K OpenSSF 5.6 5.8K dependents Pushed 4d ago 100% patched ~0d to patch Full package profile →

Do you use Tokenizers? You're affected.

How severe is it?

CVSS 3.1
7.5 / 10
EPSS
0.3%
chance of exploitation in 30 days
Higher than 26% of all CVEs
Exploitation Status
Exploit Available
Exploitation: MEDIUM
Sophistication
Trivial
Exploitation Confidence
medium
CISA SSVC: Public PoC
Public PoC indexed (trickest/cve)
Composite signal derived from CISA KEV, VulnCheck KEV, CISA SSVC, EPSS, Metasploit, Exploit-DB, trickest/cve, Nuclei templates, and inthewild.io exploitation reports.

What is the attack surface?

AV AC PR UI S C I A
AV Network
AC Low
PR None
UI None
S Unchanged
C None
I None
A High

What should I do?

6 steps
  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 does CISA's SSVC say?

Decision Track*
Exploitation poc
Automatable Yes
Technical Impact partial

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:

EU AI Act
Article 15 - Accuracy, Robustness and Cybersecurity Article 9 - Risk Management System
ISO 42001
6.1.2 - AI Risk Assessment 8.4 - AI System Operation
NIST AI RMF
MANAGE 2.2 - Mechanisms to Respond to AI Risks
OWASP LLM Top 10
LLM10:2025 - Unbounded Consumption

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

LLM-powered chatbotsAgent framework UIsRAG front-end interfacesAI documentation generation systemsModel serving API gateways with markdown rendering

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

EU AI Act: Article 15, Article 9
ISO 42001: 6.1.2, 8.4
NIST AI RMF: MANAGE 2.2
OWASP LLM Top 10: LLM10:2025

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: 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

Timeline

Published
April 29, 2026
Last Modified
April 29, 2026
First Seen
April 30, 2026

Related Vulnerabilities