Skip to main content
CVE Vulnerability Database
Vulnerability Database/CVE-2026-48988

CVE-2026-48988: markdown-it DOS Vulnerability

CVE-2026-48988 is a denial-of-service vulnerability in markdown-it that causes excessive CPU consumption through quadratic processing when typographer mode is enabled. This article covers technical details, affected versions, and mitigation.

Published:

CVE-2026-48988 Overview

CVE-2026-48988 is a denial-of-service vulnerability in markdown-it, a widely used JavaScript Markdown parser. Versions 14.1.1 and below contain quadratic O(n^2) processing in the smartquotes rule when the typographer: true option is enabled. The flaw resides in replaceAt(), which performs O(n) string slicing and concatenation for each quote character processed. Attackers can submit quote-heavy markdown to exhaust CPU resources and degrade service availability. Although typographer is disabled by default, many production applications enable it for smart typography rendering. The issue is fixed in version 14.2.0.

Critical Impact

Attackers can submit crafted markdown input containing many quote characters to trigger excessive CPU consumption, disrupting availability of services that parse untrusted markdown.

Affected Products

  • markdown-it versions 14.1.1 and earlier
  • Applications enabling the typographer: true parser option
  • Downstream packages and services that accept user-supplied markdown

Discovery Timeline

  • 2026-06-17 - CVE-2026-48988 published to NVD
  • 2026-06-17 - Last updated in NVD database

Technical Details for CVE-2026-48988

Vulnerability Analysis

The vulnerability is an algorithmic complexity flaw [CWE-400] in the smartquotes processing rule of markdown-it. When typographer: true is enabled, the parser replaces straight quote characters with typographic equivalents such as the right single quotation mark (\\u2019). The original implementation called replaceAt() for each quote, which built a new string using str.slice(0, index) + ch + str.slice(index + 1). Each call traverses and copies the entire input, producing O(n^2) total work for inputs containing many quotes.

Processing large markdown documents with many quote characters causes CPU consumption to grow quadratically. A single worker thread handling such input can stall, blocking concurrent requests on Node.js event-loop-bound servers. This degrades service availability without requiring authentication.

Root Cause

The root cause is repeated O(n) string mutation inside an O(n) loop. JavaScript strings are immutable, so every replaceAt() call allocates a new string of length n and copies the contents. Performing this once per quote token yields quadratic time complexity relative to input size.

Attack Vector

Exploitation requires only the ability to submit markdown input to a vulnerable application. An unauthenticated attacker sends a payload containing a large number of quote characters to any endpoint that renders user-supplied markdown with the typographer option enabled. The server consumes CPU cycles processing the smartquotes rule, blocking the event loop and degrading throughput for other clients.

text
// Patch excerpt from lib/rules_core/smartquotes.mjs
 const QUOTE_RE = /['"]/g
 const APOSTROPHE = '\\u2019' /* ’ */
 
-function replaceAt (str, index, ch) {
-  return str.slice(0, index) + ch + str.slice(index + 1)
+function addReplacement (replacements, tokenIdx, pos, ch) {
+  if (!replacements[tokenIdx]) {
+    replacements[tokenIdx] = []
+  }
+
+  replacements[tokenIdx].push({ pos, ch })
+}
+
+function applyReplacements (str, replacements) {
+  let result = ''
+  let lastPos = 0
+
+  replacements.sort((a, b) => a.pos - b.pos)
+
+  for (let i = 0; i < replacements.length; i++) {
+    const replacement = replacements[i]
+
+    result += str.slice(lastPos, replacement.pos) + replacement.ch
+    lastPos = replacement.pos + 1
+  }
+
+  return result + str.slice(lastPos)
 }
 
 function process_inlines (tokens, state) {

Source: GitHub Commit 9ce2087

The patch replaces in-place string rewriting with a batched approach. Replacements are collected into an array and applied in a single linear pass via applyReplacements(), reducing complexity from O(n^2) to O(n).

Detection Methods for CVE-2026-48988

Indicators of Compromise

  • Sustained high CPU usage on Node.js processes that parse user-supplied markdown.
  • HTTP request payloads containing unusually high ratios of ' or " characters relative to overall size.
  • Increased request latency or event-loop lag metrics correlated with markdown rendering endpoints.

Detection Strategies

  • Inventory dependencies using npm ls markdown-it to identify projects pinned to versions <= 14.1.1.
  • Audit parser initialization code for typographer: true or .set({ typographer: true }) to find exposed configurations.
  • Inspect upstream proxies and Web Application Firewall logs for oversized markdown payloads with anomalous quote density.

Monitoring Recommendations

  • Track Node.js event-loop lag and per-request CPU time on services that render markdown.
  • Alert on request body sizes exceeding expected thresholds for markdown rendering endpoints.
  • Log and rate-limit anonymous submissions to public markdown rendering APIs.

How to Mitigate CVE-2026-48988

Immediate Actions Required

  • Upgrade markdown-it to version 14.2.0 or later across all projects and lockfiles.
  • Disable the typographer option where smart typography is not required.
  • Enforce request body size limits and per-client rate limits on markdown rendering endpoints.

Patch Information

The fix is included in markdown-it version 14.2.0. The change replaces the quadratic replaceAt() routine with a linear batched applyReplacements() function. See GitHub Security Advisory GHSA-6v5v-wf23-fmfq and GitHub Commit 9ce2087 for full details.

Workarounds

  • Set typographer: false when constructing the markdown-it instance to bypass the vulnerable code path.
  • Cap input length for untrusted markdown before passing it to the parser.
  • Offload markdown rendering to isolated worker processes with CPU time limits.
bash
# Upgrade markdown-it to the patched release
npm install markdown-it@^14.2.0

# Verify installed version
npm ls markdown-it

# Safe initialization without smartquotes processing
# const md = require('markdown-it')({ typographer: false })

Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.

Default Legacy - Prefooter | Experience the World’s Most Advanced Cybersecurity Platform

Experience the Most Advanced Cybersecurity Platform

See how the world’s most intelligent, autonomous cybersecurity platform can protect your organization today and into the future.