CVEReports
CVEReports

Automated vulnerability intelligence platform. Comprehensive reports for high-severity CVEs generated by AI.

Product

  • Home
  • Sitemap
  • RSS Feed

Company

  • About
  • Contact
  • Privacy Policy
  • Terms of Service

© 2026 CVEReports. All rights reserved.

Made with love by Amit Schendel & Alon Barad



CVE-2026-23874
5.50.01%

Infinite Loops & Infinite Sadness: The MSL Ouroboros in ImageMagick (CVE-2026-23874)

Amit Schendel
Amit Schendel
Senior Security Researcher

Feb 16, 2026·6 min read·9 visits

PoC Available

Executive Summary (TL;DR)

ImageMagick < 7.1.2-13 crashes if you feed it an XML script (MSL) that writes to the 'msl:' format. The parser calls the writer, which calls the parser, ad infinitum. Fix available.

A stack overflow vulnerability in ImageMagick's Magick Scripting Language (MSL) interpreter allows local attackers to crash the application via infinite recursion. By instructing the MSL parser to 'write' an image back into the MSL format, the parser triggers a self-referential loop that exhausts the stack, leading to a Denial of Service (DoS).

The Hook: The Swiss Army Chainsaw

ImageMagick is the 'duct tape' of the internet. It is the software library responsible for resizing your profile picture on forums, converting your PDFs to JPEGs, and generally handling image manipulation on millions of servers worldwide. Because it tries to support every file format known to humanity—from the mundane PNG to the esoteric SUN Rasterfile—it has a massive attack surface. Complexity is the enemy of security, and ImageMagick is very complex.

One of the darker corners of ImageMagick is the Magick Scripting Language (MSL). Did you know ImageMagick has its own XML-based scripting language? Neither did most sysadmins. It allows you to define image processing pipelines in an XML file rather than chaining command-line arguments. While powerful, it introduces the classic vulnerability vector: a parser that executes logic defined by untrusted input.

CVE-2026-23874 is a reminder that obscure features are often the most fragile. It’s a stack overflow vulnerability caused by a logic flaw in how MSL handles file writing. It’s not a memory corruption bug in the traditional buffer overflow sense—no heap spraying required here. Instead, it’s a logic bomb that forces the application to eat its own tail until it explodes.

The Flaw: Recursion implies Recursion

The vulnerability resides in coders/msl.c, specifically in how the MSL parser handles the <write> tag. In a normal workflow, an MSL script reads an image, performs some operations (resize, crop, blur), and then writes the result to a file.

Here is the logic flaw: ImageMagick treats file formats as abstractions. If you write to output.jpg, it calls the JPEG encoder. If you write to output.png, it calls the PNG encoder. But what happens if you write to output.msl?

When the <write> tag specifies the msl: protocol or an .msl extension, ImageMagick invokes the MSL writer. However, because MSL is a scripting language, 'writing' to it isn't just dumping bytes; in the context of this specific coder, the implementation inadvertently triggers the parsing logic again to handle the structure. This creates a recursive loop: The Parser encounters <write> -> Calls WriteImage -> Selects MSL Coder -> MSL Coder invokes processing -> Parser starts again.

Without a depth limit or a check to prevent the MSL coder from being invoked recursively during a write operation, the function calls pile up on the stack. Eventually, the stack pointer hits the guard page, the OS screams, and the process terminates with a segmentation fault. It's a classic Denial of Service via resource exhaustion.

The Code: Diffing the Disaster

Let's look at the smoking gun in coders/msl.c. The vulnerability was patched in commit 2a09644b10a5b146e0a7c63b778bd74a112ebec3. Below is the critical logic inside MSLStartElement, the function responsible for parsing XML tags in the script.

Before the Fix:

/* Vulnerable Logic */
if (LocaleCompare((char *) tag,"write") == 0)
{
  // ... setup image info ...
  (void) WriteImage(msl_info->image_info[n], 
                    msl_info->image[n], 
                    msl_info->exception);
  break;
}

The code simply blindly calls WriteImage with whatever filename and format the user provided in the XML attributes. If the user provided msl:, WriteImage re-enters the MSL machinery.

After the Fix:

/* Patched Logic */
(void) CopyMagickString(msl_info->image_info[n]->filename,
  msl_info->image[n]->filename,MagickPathExtent);
(void) SetImageInfo(msl_info->image_info[n],1,exception);
 
/* The Check */
if (LocaleCompare(msl_info->image_info[n]->magick,"msl") != 0)
  {
    *msl_info->image_info[n]->magick='\0';
    (void) WriteImage(msl_info->image_info[n],msl_info->image[n],
      msl_info->exception);
  }
else
  (void) ThrowMagickException(msl_info->exception,GetMagickModule(),
    FileOpenError,"UnableToWriteFile","`%s'",
    msl_info->image[n]->filename);

The fix is a hard stop. The developers added a check using LocaleCompare to see if the resolved magic format is "msl". If it is, they throw a FileOpenError exception immediately, preventing the recursive call to WriteImage. It's a crude but effective patch: "Doctor, it hurts when I do this." "Then don't do that."

The Exploit: Crashing the Party

Exploiting this is trivially easy if you can feed an MSL file to ImageMagick. This might happen in web applications that allow users to upload 'image' files but fail to validate the file header, passing everything to magick convert.

Here is a Proof-of-Concept (PoC) crash.msl:

<?xml version="1.0" encoding="UTF-8"?>
<image>
  <read filename="logo:" />
  <write filename="msl:recursion.msl" />
</image>

The Execution Flow:

  1. Loader: You run magick crash.msl.
  2. Read: ImageMagick reads the built-in logo: image into memory.
  3. Write: The parser hits the <write> tag. The filename starts with msl:, forcing the MSL coder.
  4. Recursion: The MSL coder attempts to process the output operation, re-invoking the MSL parsing context.
  5. Loop: Steps 3 and 4 repeat instantly.
  6. Crash: The stack exhausts, and the application segfaults.

While this is primarily a Denial of Service (DoS), never underestimate the chaos a reliable crash can cause. In a serverless environment (like AWS Lambda), this might just cost the attacker money. In a persistent server environment, repeatedly crashing the image processor can fill logs, exhaust thread pools if the crash isn't handled cleanly, or destabilize the entire service.

The Impact: Why Should We Care?

In the grand scheme of things, a CVSS 5.5 (Local DoS) isn't going to make the evening news. However, for a service provider hosting an image conversion API, this is a nuisance. If your architecture relies on ImageMagick processing files from untrusted users, this bug allows any user to kill the worker process handling their request.

If the worker process is not isolated (e.g., it's a thread in a larger application rather than a spawned process), this vulnerability brings down the whole application. The attack complexity is low, and no special privileges are needed beyond the ability to submit a file.

Furthermore, this highlights the danger of 'Polyglot' inputs. An attacker might hide this XML payload inside a valid-looking image file or change the extension to .jpg hoping the detection logic relies solely on file extensions, while ImageMagick's magic-byte detection might still decide to treat it as MSL text.

The Fix: Stopping the Bleeding

If you are running ImageMagick, you have two options. The first and best option is to upgrade. Version 7.1.2-13 includes the patch that explicitly forbids writing to MSL formats from within an MSL script.

If you cannot upgrade immediately (perhaps you are dependent on a specific legacy version for other reasons), you can use ImageMagick's robust policy.xml framework to neuter the attack vector. The policy.xml file allows administrators to disable specific coders.

Mitigation via Policy:

Add the following line to your policy.xml (usually found in /etc/ImageMagick-7/):

<policy domain="coder" rights="none" pattern="MSL" />

This policy completely disables the MSL coder. Unless your application specifically requires the ability to execute MSL scripts (which is rare for standard web apps), this is a safe and highly recommended hardening step regardless of this specific CVE. It closes the door not just on this bug, but on any future bugs found in the MSL interpreter.

Official Patches

ImageMagickGitHub Commit fixing the recursion issue

Fix Analysis (1)

Technical Appendix

CVSS Score
5.5/ 10
CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:N/I:N/A:H
EPSS Probability
0.01%
Top 100% most exploited

Affected Systems

ImageMagick < 7.1.2-13

Affected Versions Detail

Product
Affected Versions
Fixed Version
ImageMagick
ImageMagick Studio LLC
< 7.1.2-137.1.2-13
AttributeDetail
CWE IDCWE-835
Bug ClassStack Overflow / Infinite Recursion
CVSS v3.15.5 (Medium)
Attack VectorLocal (File Processing)
EPSS Score0.014%
KEV StatusNot Listed

MITRE ATT&CK Mapping

T1499Endpoint Denial of Service
Impact
T1203Exploitation for Client Execution
Execution
CWE-835
Infinite Loop

Loop with Unreachable Exit Condition ('Infinite Loop')

Known Exploits & Detection

Internal ResearchThe exploit involves creating an MSL XML file that writes to an 'msl:' target, causing an infinite loop.

Vulnerability Timeline

Fix commit authored in ImageMagick repository
2026-01-15
ImageMagick version 7.1.2-13 released
2026-01-19
CVE-2026-23874 published
2026-01-20

References & Sources

  • [1]GitHub Advisory GHSA-9vj4-wc7r-p844
  • [2]Magick Scripting Language Documentation

Attack Flow Diagram

Press enter or space to select a node. You can then use the arrow keys to move the node around. Press delete to remove it and escape to cancel.
Press enter or space to select an edge. You can then press delete to remove it or escape to cancel.