CVEReports
CVEReports

Automated vulnerability intelligence platform. Comprehensive reports for high-severity CVEs generated by AI.

Product

  • Home
  • Sitemap
  • RSS Feed

Company

  • About
  • Contact
  • Privacy Policy
  • Terms of Service

© 2026 CVEReports. All rights reserved.

Made with love by Amit Schendel & Alon Barad



CVE-2026-41680
7.50.07%

CVE-2026-41680: Denial of Service via Infinite Recursion in marked Lexer

Amit Schendel
Amit Schendel
Senior Security Researcher

Apr 30, 2026·6 min read·4 visits

PoC Available

Executive Summary (TL;DR)

Unauthenticated DoS in marked via a 3-byte payload (\t\v\n) causing infinite loops and Out-of-Memory crashes.

The marked Node.js Markdown parser versions 18.0.0 and 18.0.1 contain a critical vulnerability where a specific 3-byte sequence triggers infinite recursion. This flaw leads to rapid memory exhaustion and application denial of service.

Vulnerability Overview

The marked library serves as a widely deployed Markdown parser and compiler for Node.js environments. Applications frequently utilize this package to process untrusted user input into HTML output. Versions 18.0.0 and 18.0.1 contain a logic error in the tokenization process that leads to unbounded resource consumption.

The vulnerability is classified as CWE-835 (Loop with Unreachable Exit Condition) and CWE-400 (Uncontrolled Resource Consumption). An unauthenticated attacker can trigger this flaw by submitting a specifically crafted three-byte character sequence. The parser fails to process these characters correctly, entering a recursive loop that allocates memory continuously.

The attack surface includes any application endpoint that accepts user-supplied Markdown and processes it using a vulnerable version of the library. Common examples include comment systems, forum post rendering, and document management applications. The vulnerability requires no non-default configurations or specialized deployment architectures.

Successful exploitation results in rapid heap memory exhaustion within the Node.js process. The application subsequently crashes with an Out-of-Memory (OOM) error, dropping all active connections and rendering the service unavailable.

Root Cause Analysis

The root cause exists within the Lexer's legacy ASCII whitespace character processing routines. The vulnerability specifically involves the space tokenizer's regular expression, which evaluates what constitutes a blank line or ignorable spacing. This regex successfully consumes standard spaces and horizontal tabs, but it explicitly excludes the Vertical Tab (\x0b) character.

When the parser processes an indented line starting with a horizontal tab (\x09) followed by a Vertical Tab and a newline, it attempts to route the input through the indented code block rules. The space tokenizer fails to consume the sequence because the Vertical Tab breaks the regex matching logic. The lexer then falls back to the text tokenizer to handle the unparsed characters.

In the vulnerable 18.0.x versions, the fallback logic fails to properly advance the source string pointer (src) when processing this exact character sequence. Because the pointer does not advance, the remaining input string is never reduced in length. The parser subsequently invokes inlineTokens() recursively on the exact same input string.

This creates an infinite loop where the parser continuously generates new token objects and concatenates string metadata. The lack of a terminal condition causes the process to allocate memory on the heap indefinitely. The Node.js garbage collector cannot reclaim this memory because the active recursion stack maintains references to the token objects.

Code Analysis

The vulnerability stems from the absence of a progress validation check in the main tokenization loop. The vulnerable implementation processes the src string through various tokenizers, assuming that at least one tokenizer will consume characters and shorten the string. When the specific \t\v\n payload is encountered, this assumption fails.

The maintainers resolved the issue in version 18.0.2 by implementing a robust progress guard within src/Lexer.ts. The patch records the initial length of the string at the beginning of each iteration. After all tokenizers execute, the code compares the new string length against the initial length to verify progress.

// Conceptual representation of the fix in Lexer.ts
while (src) {
  const srcLength = src.length; // Guard variable added
 
  // Tokenizer execution logic...
 
  if (srcLength === src.length) { // Validation check
    const infiniteLoopError = new Error('infinite loop');
    throw infiniteLoopError;
  }
}

This structural fix is comprehensive because it addresses the bug class rather than simply adding the Vertical Tab to the whitespace regex. By enforcing strict progress validation, the parser defends against any future parsing edge cases that might result in unconsumed input. The maintainers also updated trimTrailingBlankLines in src/helpers.ts to use consistent regex validation across environments.

Exploitation

Exploitation requires the attacker to submit a precise three-byte payload to the target application. The exploit sequence consists of a horizontal tab (\x09), a Vertical Tab (\x0b), and a newline (\x0a). This payload is small enough to bypass most length-based input validation controls.

The attack methodology involves identifying an endpoint that routes user input to the marked library. The attacker then issues an HTTP POST request or WebSocket message containing the payload. No authentication or elevated privileges are required to deliver the payload to exposed endpoints.

Upon processing the payload, the target server's CPU utilization spikes to 100% on the single thread running the event loop. System memory consumption rises sharply as the parser allocates continuous heap space. Depending on the container memory limits or physical server specifications, the process crashes with ERR_WORKER_OUT_OF_MEMORY within seconds.

Impact Assessment

The primary impact of this vulnerability is total Denial of Service (DoS) for the affected Node.js process. Because Node.js operates primarily on a single-threaded event loop, the infinite recursion blocks all concurrent operations. Legitimate requests queued on the event loop remain unfulfilled while the parser exhausts system resources.

In architectures lacking robust health checks and automatic restart policies, a single malicious request can permanently disable the service. In orchestrated environments like Kubernetes, the OOM crash will trigger container restarts. However, continuous exploitation will result in a crash-loop state, sustaining the availability impact.

The vulnerability is scored as a 7.5 High under CVSS v3.1 and an 8.7 High under CVSS v4.0. The high scores reflect the trivial network exploitability and the complete loss of availability. The exploit requires no user interaction and operates against default configurations.

The current EPSS percentile is relatively low at 20.26%. This metric indicates the initial probability of exploitation in the wild at the time of disclosure. Given the functional and trivial nature of the PoC, threat actors can easily incorporate this payload into automated scanning and exploitation frameworks targeting Markdown-enabled web applications.

Remediation

The definitive remediation is upgrading the marked library to version 18.0.2 or later. The patch introduces fundamental structural safeguards that terminate the parsing process if infinite recursion is detected. Developers should verify the dependency tree to ensure transitive dependencies are also updated.

If immediate patching is not technically feasible, organizations must implement application-level input sanitization. Middleware components can intercept incoming requests and strip or replace Vertical Tab (\x0b) characters before they reach the parser. This prevents the specific payload sequence from triggering the logic error.

Network defenders can deploy Web Application Firewall (WAF) rules to detect and drop HTTP requests containing the hex sequence 09 0b 0a. This signature specifically matches the proof-of-concept payload and blocks exploitation attempts at the edge network layer.

As a defense-in-depth measure, Node.js applications should be configured with explicit heap limits using the --max-old-space-size flag. Additionally, utilizing process managers like PM2 or container orchestration policies ensures the application automatically recovers from unexpected crashes, limiting the duration of the denial of service.

Official Patches

markedjsGitHub Security Advisory GHSA-6v9c-7cg6-27q7
markedjsFix Commit in Lexer.ts

Fix Analysis (1)

Technical Appendix

CVSS Score
7.5/ 10
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H
EPSS Probability
0.07%
Top 80% most exploited

Affected Systems

Node.js applications running marked versions 18.0.0 through 18.0.1Systems processing untrusted Markdown input via affected marked versions

Affected Versions Detail

Product
Affected Versions
Fixed Version
marked
markedjs
18.0.0 - 18.0.118.0.2
AttributeDetail
CWE IDCWE-835, CWE-400
Attack VectorNetwork
CVSS v3.17.5 (High)
EPSS Score0.07%
ImpactDenial of Service (OOM)
Exploit StatusPoC Available

MITRE ATT&CK Mapping

T1499Endpoint Denial of Service
Impact
CWE-835
Loop with Unreachable Exit Condition ('Infinite Loop')

Loop with Unreachable Exit Condition ('Infinite Loop')

Known Exploits & Detection

Research Report3-byte payload comprising Tab (\x09), Vertical Tab (\x0b), and Newline (\n)

Vulnerability Timeline

Fix commit merged and version 18.0.2 released
2026-04-18
CVE-2026-41680 published to the NVD and CVE.org
2026-04-24
Last major update to NVD record and references
2026-04-28

References & Sources

  • [1]GHSA-6v9c-7cg6-27q7
  • [2]Fix Commit
  • [3]NVD Record
  • [4]CVE.org Record

Attack Flow Diagram

Press enter or space to select a node. You can then use the arrow keys to move the node around. Press delete to remove it and escape to cancel.
Press enter or space to select an edge. You can then press delete to remove it or escape to cancel.