High priorityDisclosed

Advisory · CVE-2026-115353

Mistune include directive reads arbitrary files into rendered output

Mistune before 3.3.0, when the RST include directive is enabled, accepts unconstrained relative and absolute include paths, so any markdown the renderer processes can read arbitrary files readable by the rendering process and embed them in the rendered HTML. CVSS 3.1 8.6, CVSS 4.0 9.2.

Vendor
Lepture
Product
Mistune
Identifier / CWE
CVE-2026-115353
CWE-22
Action timing
Immediate
ELI5

Explain it like I’m five

The include feature was meant to let a document pull in a neighboring file. It never checked that the file actually is a neighbor, so a document can ask for the server password file instead and have its contents printed into the page.

SIMPLIFIED_ATTACK_PATH04 STEPS
  1. 01Application renders markdown with includes

    An application uses Mistune to render markdown with the RST directive and Include plugin enabled, and sets the source file path so relative includes resolve, which the advisory describes as the documented setup.

  2. 02Attacker submits a crafted include

    The attacker submits markdown whose include directive names a relative traversal path or an absolute path to a sensitive file.

  3. 03Path is resolved without containment

    Per the Mistune advisory, the plugin normalizes the joined path but does not constrain the result to the source file directory, has no allowlist, and does not reject traversal or absolute paths.

  4. 04File contents are rendered

    The plugin opens any file readable by the rendering process and embeds its contents in the rendered output, which the attacker can read back from wherever the application displays it.

What happened

The Mistune project disclosed CVE-2026-115353 in its GitHub security advisory: the include directive in the RST directive plugin accepts unconstrained relative and absolute paths, allowing arbitrary file read by any markdown the renderer processes. Per the advisory, the plugin takes the directive argument verbatim, joins it to the source file directory and normalizes the result, but normalization does not enforce containment, and an absolute path discards the base entirely; the only guards are rejecting self-inclusion and requiring that the target is a file. The CVE record lists Mistune before 3.3.0 as affected, with 3.3.0 as the fixed release. The CVSS 3.1 score is 8.6, with changed scope, and the CVSS 4.0 score is 9.2.

Per the advisory, the attacker capability is to read any file the rendering process can open, which on a typical web stack includes system password files, process environment data, application environment and settings files holding database credentials and signing keys, log files, and home directory credential files. The preconditions are that the application renders markdown with the Include plugin enabled and sets the source file path in the render environment, which the advisory describes as the documented integration for rendering markdown files from disk. Combined with HTML escaping disabled, including an HTML file also becomes a stored cross-site scripting primitive, per the advisory.

What to do

  1. Inventory Python applications and services that use Mistune, and check which of them enable the RST directive Include plugin or render markdown files from disk with a source path set.
  2. Upgrade Mistune to 3.3.0 or later in every affected application, using the project release guidance.
  3. Until upgraded, disable the Include plugin anywhere untrusted markdown is rendered, or constrain includes to a dedicated content directory at the application layer.
  4. Hunt rendered output and rendering logs for include directives carrying traversal sequences or absolute paths, and for rendered pages containing file contents such as environment data.
  5. If suspicious includes are found, treat files readable by the rendering process as exposed and rotate the credentials they contained.

Management note

Markdown rendering is often treated as a safe formatting step. With the include plugin on, it is a file read primitive against everything the service account can open, so find the renderers that enabled it and patch them as internet-facing code.