CVE-2026-2327
Description
Versions of the package markdown-it from 13.0.0 and before 14.1.1 are vulnerable to Regular Expression Denial of Service (ReDoS) due to the use of the regex /\*+$/ in the linkify function. An attacker can supply a long sequence of * characters followed by a non-matching character, which triggers excessive backtracking and may lead to a denial-of-service condition.
AI Insight
LLM-synthesized narrative grounded in this CVE's description and references.
markdown-it versions 13.0.0 to 14.1.0 are vulnerable to ReDoS via crafted input with many asterisks in the linkify function.
Vulnerability
The vulnerability is a Regular Expression Denial of Service (ReDoS) in the linkify function of the markdown-it library. The root cause is the use of the regex /*+$/ to strip trailing asterisks from URLs. This regex exhibits catastrophic backtracking when processing a long sequence of * characters followed by a non-matching character, such as a letter or digit [1][3].
Exploitation
An attacker can exploit this by providing a crafted input string containing a long run of asterisks (e.g., ****...****a) to an application that uses markdown-it to render user-supplied Markdown. The linkify function attempts to match the regex against the input, causing the regex engine to backtrack excessively. No authentication or special network position is required; the attack can be performed by any user who can submit Markdown content [1][2].
Impact
Successful exploitation leads to high CPU consumption, potentially causing a denial-of-service condition. The application may become unresponsive or crash, affecting availability for legitimate users. The Snyk advisory notes that ReDoS attacks can make a system inaccessible [3].
Mitigation
The issue is fixed in markdown-it version 14.1.1, released on 2026-01-11. The fix replaces the regex with a manual back-search loop, eliminating the backtracking problem [4]. Users should upgrade to version 14.1.1 or later. No workarounds are documented; disabling the linkify feature may reduce risk but is not a complete solution.
AI Insight generated on May 19, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.
Affected packages
Versions sourced from the GitHub Security Advisory.
| Package | Affected versions | Patched versions |
|---|---|---|
markdown-itnpm | >= 13.0.0, < 14.1.1 | 14.1.1 |
Affected products
2>=13.0.0 <14.1.1+ 1 more
- (no CPE)range: >=13.0.0 <14.1.1
- (no CPE)range: 13.0.0
Patches
14b4bbcae5e09Fixed perf regression in linkify-it wrapper
4 files changed · +25 −5
CHANGELOG.md+6 −0 modified@@ -5,6 +5,11 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [14.1.1] - 2026-01-11 +### Security +- Fixed regression from v13 in linkify inline rule. Specific patterns could + cause high CPU use. Thanks to @ltduc147 for report. + ## [14.1.0] - 2024-03-19 ### Changed @@ -648,6 +653,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Renamed presets folder (configs -> presets). +[14.1.1]: https://github.com/markdown-it/markdown-it/compare/14.1.0...14.1.1 [14.1.0]: https://github.com/markdown-it/markdown-it/compare/14.0.0...14.1.0 [14.0.0]: https://github.com/markdown-it/markdown-it/compare/13.0.2...14.0.0 [13.0.2]: https://github.com/markdown-it/markdown-it/compare/13.0.1...13.0.2
lib/rules_inline/linkify.mjs+8 −1 modified@@ -30,7 +30,14 @@ export default function linkify (state, silent) { if (url.length <= proto.length) return false // disallow '*' at the end of the link (conflicts with emphasis) - url = url.replace(/\*+$/, '') + // do manual backsearch to avoid perf issues with regex /\*+$/ on "****...****a". + let urlEnd = url.length + while (urlEnd > 0 && url.charCodeAt(urlEnd - 1) === 0x2A/* * */) { + urlEnd-- + } + if (urlEnd !== url.length) { + url = url.slice(0, urlEnd) + } const fullUrl = state.md.normalizeLink(url) if (!state.md.validateLink(fullUrl)) return false
test/pathological.mjs+9 −2 modified@@ -4,7 +4,7 @@ import crypto from 'node:crypto' import { Worker as JestWorker } from 'jest-worker' import { readFileSync } from 'fs' -async function test_pattern (str) { +async function test_pattern (str, mdOpts) { const worker = new JestWorker( new URL('./pathological_worker.js', import.meta.url), { @@ -18,7 +18,7 @@ async function test_pattern (str) { try { result = await Promise.race([ - worker.render(str), + worker.render(str, mdOpts), new Promise((resolve, reject) => { setTimeout(() => reject(new Error('Terminated (timeout exceeded)')), 3000).unref() }) @@ -163,5 +163,12 @@ describe('Pathological sequences speed', () => { it('hardbreak whitespaces pattern', async () => { await test_pattern('x' + ' '.repeat(150000) + 'x \nx') }) + + it('linkify-it wrapper trailing asterisks pattern', async () => { + await test_pattern( + 'https://test.com?' + '*'.repeat(70000) + 'a', + { linkify: true } + ) + }) }) })
test/pathological_worker.js+2 −2 modified@@ -1,5 +1,5 @@ 'use strict' -exports.render = async (str) => { - return (await import('../index.mjs')).default().render(str) +exports.render = async (str, mdOpts) => { + return (await import('../index.mjs')).default(mdOpts).render(str) }
Vulnerability mechanics
Generated on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
7- github.com/advisories/GHSA-38c4-r59v-3vqwghsaADVISORY
- nvd.nist.gov/vuln/detail/CVE-2026-2327ghsaADVISORY
- gist.github.com/ltduc147/c9abecae1b291ede4f692f2ab988c917ghsaWEB
- github.com/markdown-it/markdown-it/blob/14.1.0/lib/rules_inline/linkify.mjsghsaWEB
- github.com/markdown-it/markdown-it/commit/4b4bbcae5e0990a5b172378e507b33a59012ed26ghsaWEB
- security.snyk.io/vuln/SNYK-JS-MARKDOWNIT-10666750ghsaWEB
- github.com/markdown-it/markdown-it/blob/14.1.0/lib/rules_inline/linkify.mjs%23L33mitre
News mentions
0No linked articles in our index yet.