Your RSA-2048 keys break in 2030. Find every one of them before attackers do.
📦
📦 npm
Not in CISA KEV
HIGH severity

CVE-2026-59887 — linkify-it

HIGHFix: markdown-it/linkify-it@105e5d7

CVE-2026-59887 is a high-severity (CVSS 7.5) CWE-407 vulnerability in linkify-it. A fix is available for linkify-it — see the affected versions and patch details below.

linkify-it: Quadratic-complexity DoS via the `mailto:` validator scan-loop on attacker text

Also known asGHSA-v245-v573-v5vm
Published
Updated
Affected
1 pkg
Patched
1 / 1
Exploits
None indexed
Exploitation data as of Oct 11, 2026 · OSV.dev, NVD, FIRST.org (EPSS)

Exploitation Status

Proof-of-concept exploit code exists

  • CISA’s SSVC triage found public proof-of-concept exploit code for this CVE, though no confirmed active exploitation.
  • CISA assesses this as automatable — exploitation doesn’t require manual, per-target effort, which raises the odds of mass scanning and opportunistic attacks.

Exploitation and automatability from CISA’s SSVC triage for CVE-2026-59887.

EPSS Exploitation Probability

via FIRST.org ↗
0.6%probability of exploitation in next 30 days
Lower Risk0.00%
Lower risk than most CVEs49th percentile — riskier than 49% of all scored CVEsHighest risk
0.00%0.38%0.76%1.14%0.3%0.4%0.6%0.6%Aug 26Oct 26Oct 26

Probability of exploitation in the next 30 days, from FIRST.org EPSS.

How urgent is this, really

CVE-2026-59887 by exploitation likelihood (EPSS) against impact (CVSS). Outside the shaded patch-first corner.

Where this sits among everything scored

Of 385,738 CVEs with a current EPSS score, this one falls in the < 10% band (highlighted). Counts from FIRST.org, log-scaled.

Real-World Exposure

1 pkg affected

How broadly this vulnerability is actually deployed: weekly install volume shows current usage, and reverse-dependency count shows how many other packages break if it stays unpatched.

458other npm packages depend on this — each one inherits the vulnerability until it's patched upstream
linkify-itnpm
34.8Mdownloads / week

Description

Summary

linkify-it's schema-scan loop (.test() / .match(), the documented public API) invokes the mailto: schema validator at every mailto: occurrence in the input text. For each occurrence the validator does text.slice(pos) (an O(n) copy) and runs an email regex whose local-part class src_email_name greedily scans the entire remaining tail (O(n)) before failing. With N mailto: occurrences that is N × O(n) = O(n²). Because linkify-it runs on arbitrary user text (markdown-it feeds it whole documents when linkify:true), an unauthenticated attacker can block the single-threaded event loop for many seconds with a small input. No length bound (unlike an HTTP header).

Root cause — index.mjs + lib/re.mjs

// index.mjs (mailto validator) — runs at every "mailto:" hit
'mailto:': { validate: function (text, pos, self) {
  const tail = text.slice(pos)                                  // O(n) copy per hit
  if (!self.re.mailto) self.re.mailto = new RegExp('^' + self.re.src_email_name + '@' + self.re.src_host_strict, 'i')
  if (self.re.mailto.test(tail)) { ... }                        // scans the whole O(n) tail
  return 0
}}
// lib/re.mjs:91-93 — every char of "mailto:" (incl. ':','-',';') is in this class:
re.src_email_name = '[\\-;:&=\\+\\$,\\.a-zA-Z0-9_][\\-;:&=\\+\\$,\\"\\.a-zA-Z0-9_]*'

The while ((m = re.exec(text)) !== null) { …testSchemaAt… } scan loop calls the validator at each mailto: hit; src_email_name greedily consumes the whole tail (all chars are in its class) then fails for lack of @. http:/https: do NOT blow up — their validator requires the tail to start with //, failing in O(1) per hit.

Proof of Concept (confirmed, linkify-it 5.0.1, Node v24)

const LinkifyIt = require('linkify-it');
const lf = new LinkifyIt();
lf.match('mailto:'.repeat(48000));   // ~336 KB of "mailto:mailto:…" -> seconds of blocked event loop
input (same bytes)56 KB112 KB224 KB336 KB
mailto: contiguous97 ms357 ms1438 ms3272 ms
mailto: space-separated2 ms3 ms5 ms8 ms
http:// contiguous12 ms17 ms33 ms49 ms

×~4 per 2× input ⇒ O(n²); equal-byte controls stay flat ⇒ algorithmic, not a GC/allocation artifact. Real-world via markdown-it 14.x ({linkify:true}), md.render('mailto:'.repeat(n)): 219 KB ≈ ~5 s. <img width="737" height="161" alt="image" src="https://github.com/user-attachments/assets/b5d390f3-68d0-4861-9c47-ad8aff0203d5" />

Impact

Reachable on arbitrary user text via the documented .test()/.match() API and through markdown-it's linkifier — comment systems, chat, forums, wikis, note apps that render user markdown with linkify enabled. A ~220 KB post hangs the event loop ~5 s; a few hundred KB → tens of seconds. Availability only.

Suggested remediation

Bound the email local-part per RFC 5321 (≤64) so per-hit work is O(1), and avoid the full-tail slice:

// lib/re.mjs — cap the greedy run:
re.src_email_name = '[\\-;:&=\\+\\$,\\.a-zA-Z0-9_][\\-;:&=\\+\\$,\\"\\.a-zA-Z0-9_]{0,63}'
// index.mjs — prefer a sticky regex anchored at `pos` over text.slice(pos).

Affected / disclosure

All versions through 5.0.1 (latest); same code on master. cve-mcp/OSV report no known vulnerability for linkify-it. Distinct from markdown-it's own *-run ReDoS (CVE-2026-2327, different package/path) and the recent markdown-it DoS. Reported privately; happy to test a patch against the PoC.

Affected Packages

1 total 1 fixed
EcosystemPackageVulnerable rangeFix
📦npmlinkify-itall versions5.0.2npm install linkify-it@5.0.2

Affected Products

1 product · 1 configurations
Application
linkify-itmarkdown-it
< 5.0.2
range

Detection & mitigation playbook

Open-source dependency
  1. Detect

    Scan your dependency tree (package-lock.json, pnpm-lock.yaml, requirements.txt, go.sum, etc.) for linkify-it, including transitive dependencies — a direct dependency you never call can still pull in a vulnerable version.

  2. Fix

    Update linkify-it to 5.0.2 or later, then make sure no transitive (indirect) dependency still pins the vulnerable range — O3 confirms CVE-2026-59887 is resolved across your whole dependency graph.

  3. Workarounds

    Cap what an attacker can consume: apply request size, rate and timeout limits in front of the affected component, and run it with memory and CPU limits so exhaustion degrades one worker rather than the whole service.

Fixing This On Your OS

If you run this on a Linux distribution, patch through your package manager against the distro's own security advisory below — it tracks the exact backported fix for your release, which can ship on a different timeline (and sometimes a different severity) than the upstream project.

Red HatImportant

This is an Important denial of service vulnerability in the `linkify-it` library. Systems processing untrusted user-supplied text containing specially crafted `mailto:` links may experience excessive CPU consumption due to a quadratic complexity issue in the `mailto:` schema validator, leading to temporary service…

Workaround published by Red Hat
Mitigation for this issue is either not available or the currently available options do not meet the Red Hat Product Security criteria comprising ease of use and deployment, applicability to widespread installation base, or stability.
Source: Red Hat security advisory for CVE-2026-59887 (CC BY 4.0)
ProductFixed inAdvisory
Cluster Observability Operator 1.5.3cluster-observability-operator/monitoring-console-plugin-pf5-rhel9:1790854526RHSA-2026:74609
Red Hat OpenShift Dev Spaces 3.30devspaces/openvsx-rhel9:1789144269RHSA-2026:68754

Frequently Asked Questions

### Summary `linkify-it`'s schema-scan loop (`.test()` / `.match()`, the documented public API) invokes the `mailto:` schema validator at **every** `mailto:` occurrence in the input text. For each occurrence the validator does `text.slice(pos)` (an O(n) copy) and runs an email regex whose local-part class `src_email_name` greedily scans the **entire remaining tail** (O(n)) before failing. With N `mailto:` occurrences that is **N × O(n) = O(n²)**. Because linkify-it runs on arbitrary user text (markdown-it feeds it whole documents when `linkify:true`), an unauthenticated attacker can block the
O3 Security · Impact-Aware SCA

Is CVE-2026-59887 in your dependencies?

Find it across npm, including transitive dependencies.

CVE-2026-59887: linkify-it DoS — Fixed in 5.0.2