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

CVE-2026-54888: mdex/mdex_native DoS Vulnerability

CVE-2026-54888 is a denial of service vulnerability in mdex and mdex_native caused by uncontrolled recursion. Attackers can crash the BEAM process using nested Markdown. This article covers technical details, affected versions, and fixes.

Published:

CVE-2026-54888 Overview

CVE-2026-54888 is an uncontrolled recursion vulnerability [CWE-674] in the mdex and mdex_native Elixir Markdown libraries maintained by leandrocp. The flaw resides in two mutually recursive Rust functions, ex_document_to_comrak_ast and comrak_ast_to_ex_document, defined in the NIF source file document.rs. Neither function enforces a maximum nesting depth. An attacker who can submit Markdown to a vulnerable application can supply thousands of nested block quotes, triggering unbounded recursion across the NIF boundary and exhausting the native C stack.

Critical Impact

A single crafted Markdown document raises an uncatchable SIGSEGV inside the NIF, terminating the entire BEAM process and killing every Elixir and Erlang process on the node.

Affected Products

  • mdex from version 0.3.0 up to (but not including) 0.12.3
  • mdex_native from version 0.1.0 up to (but not including) 0.2.3
  • Any Elixir or Erlang application that renders untrusted Markdown through MDEx.parse_document!/1 or MDEx.to_html/1

Discovery Timeline

  • 2026-06-29 - CVE-2026-54888 published to the National Vulnerability Database (NVD)
  • 2026-06-30 - Last updated in NVD database

Technical Details for CVE-2026-54888

Vulnerability Analysis

The mdex library converts between the Elixir %MDEx.Document{} struct and the internal abstract syntax tree (AST) produced by the Comrak Markdown parser. This conversion is implemented in Rust as a Native Implemented Function (NIF) using two mutually recursive routines. Each nested Markdown block quote increases the recursion depth by one frame per function on the native stack.

Because neither routine tracks or caps depth, an attacker controls how deep the recursion goes. Once the native stack is exhausted, the operating system delivers SIGSEGV to the BEAM process. The Erlang runtime cannot trap signals raised from within a NIF, so the fault propagates to process termination.

The outcome is a node-wide denial of service. Every unrelated Elixir process, supervisor tree, and Erlang application running in that BEAM instance is killed alongside the caller.

Root Cause

The root cause is missing depth enforcement in the AST conversion functions inside document.rs. Recursion depth is bounded only by the structure of the input document rather than by an explicit limit. Combined with the fact that NIF code executes outside Erlang scheduler protection, a stack overflow becomes a process-terminating event instead of a recoverable error.

Attack Vector

Exploitation requires no authentication or special privileges. Any user who can submit Markdown content to a rendering path such as MDEx.parse_document!/1 or MDEx.to_html/1 can trigger the crash. Typical exposure includes comment fields, wiki pages, chat integrations, and API endpoints that accept Markdown from clients.

text
# Patch excerpt from lib/mdex_native/comrak.ex
@spec parse_document(markdown(), options()) :: MDExNative.Comrak.Document.t()
def parse_document(markdown, options \\ []) when is_binary(markdown) do
-    MDExNative.Native.parse_document(markdown, options!(options))
+    markdown
+    |> MDExNative.Native.parse_document(options!(options))
+    |> check_native_output()
end

The patch routes NIF output through check_native_output/1, which validates the returned structure and prevents unbounded native recursion from reaching a crash state. Source: GitHub commit 947696c.

Detection Methods for CVE-2026-54888

Indicators of Compromise

  • Sudden BEAM VM termination with SIGSEGV (signal 11) in kernel or systemd logs on hosts running Elixir applications that render Markdown
  • Supervisor restart storms following ingestion of user-supplied Markdown containing long runs of > characters
  • HTTP request bodies or webhook payloads containing thousands of nested block quote markers targeting Markdown rendering endpoints

Detection Strategies

  • Instrument Markdown rendering endpoints to log input size and maximum nesting depth before invoking MDEx functions
  • Alert on repeated unclean shutdowns of the BEAM process on the same node within a short window
  • Inspect reverse proxy and web application firewall (WAF) logs for payloads with abnormally deep block quote or list nesting

Monitoring Recommendations

  • Forward dmesg, journalctl, and container runtime logs to a centralized platform to correlate SIGSEGV events with request traces
  • Track deployment inventory for mdex and mdex_native versions using software bill of materials (SBOM) tooling and mix.lock scanning
  • Monitor request patterns to Markdown-accepting endpoints and rate-limit unauthenticated submissions

How to Mitigate CVE-2026-54888

Immediate Actions Required

  • Upgrade mdex to version 0.12.3 or later, and mdex_native to version 0.2.3 or later, in mix.exs and rebuild release artifacts
  • Audit application code for any call sites invoking MDEx.parse_document!/1, MDEx.to_html/1, or related rendering APIs on untrusted input
  • Deploy input size and nesting-depth checks in front of Markdown rendering until patched versions are in production

Patch Information

The vulnerable conversion code was extracted from mdex into the separate mdex_native package starting in mdex 0.12.3. Fixes are available in mdex 0.12.3 and mdex_native 0.2.3. Full remediation details are documented in the GitHub Security Advisory GHSA-3w4f-53g2-f66p and the Erlef CNA advisory.

Workarounds

  • Pre-validate Markdown input by rejecting documents that exceed a defined maximum length or contain excessive consecutive > characters
  • Isolate Markdown rendering into a dedicated BEAM node so that a crash does not affect primary application services
  • Restrict Markdown submission endpoints to authenticated users and apply per-user rate limits
bash
# Update dependencies in mix.exs and fetch patched versions
# {:mdex, "~> 0.12.3"}
# {:mdex_native, "~> 0.2.3"}
mix deps.update mdex mdex_native
mix deps.get
mix compile --force

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.