Feb 16, 2026·5 min read·14 visits
ImageMagick's MSL parser crashes if it sees a <comment> tag before an image is loaded. This NULL pointer dereference (CWE-476) causes a DoS. Fixed in Magick.NET 14.10.2.
A NULL pointer dereference vulnerability in ImageMagick's Magick Scripting Language (MSL) parser allows attackers to crash applications by supplying a malformed XML script. Specifically, defining a comment before initializing an image object triggers a segmentation fault, leading to Denial of Service.
ImageMagick is the Swiss Army knife of image processing—it's everywhere, from your favorite social media platform's thumbnail generator to the backend of enterprise content management systems. But buried deep within its vast arsenal of 'coders' (modules that handle specific file formats) lies a relic called MSL (Magick Scripting Language).
MSL is an XML-based scripting language that allows you to define image processing pipelines in a structured text file. Instead of running a complex command-line string, you pass an XML file to the MSL interpreter, and it executes the steps. Ideally, this is a powerful automation tool. Practically, it's a forgotten attack surface that most developers don't realize is enabled by default.
CVE-2026-23952 isn't a complex heap feng-shui masterpiece; it's a classic logic error in how this parser handles the order of operations. It's the digital equivalent of trying to hang a picture frame on a wall you haven't built yet. The result? The application tries to interact with a void, and the operating system kills it with prejudice.
The vulnerability resides in coders/msl.c, specifically in the function MSLEndElement. This function is responsible for handling the closing tags of XML elements. When the parser encounters a </comment> tag, it naturally assumes there is an image object currently in memory that this comment belongs to.
Under normal circumstances, an MSL script loads an image first (via <read> or <image>), allocating memory and setting up the internal structures. The parser tracks these images in an array msl_info->image[n]. When a comment is processed, the code attempts to attach metadata to msl_info->image[n].
The logic failure here is profound in its simplicity: The developers assumed that a user would never try to comment on nothing. If an attacker provides an MSL script where the <comment> tag appears before any image loading tag, msl_info->image[n] is still NULL. The code proceeds to dereference this NULL pointer to call DeleteImageProperty, resulting in an immediate crash.
Let's look at the smoking gun. In the vulnerable version of coders/msl.c, the handler for the comment tag blindly trusts that the image pointer is valid.
Vulnerable Code:
/* Inside MSLEndElement */
if (LocaleCompare(keyword,"comment") == 0)
{
/*
* CRASH: msl_info->image[n] is NULL here if no image is loaded.
* The function tries to access memory at 0x0.
*/
(void) DeleteImageProperty(msl_info->image[n],"comment");
// ... code to attach new comment ...
}The fix is the standard "check for NULL" pattern that should have been there from day one. The patch simply wraps the operation in a conditional check.
Fixed Code:
if (LocaleCompare(keyword,"comment") == 0)
{
/*
* FIX: Verify the pointer exists before touching it.
*/
if (msl_info->image[n] != (Image *) NULL)
(void) DeleteImageProperty(msl_info->image[n],"comment");
// ...
}This creates a safety check: if the image doesn't exist, the parser just ignores the cleanup attempt instead of committing suicide.
Exploiting this requires no shellcode, no ROP chains, and no memory leaks. You just need to pass a valid XML file that violates the parser's logical expectations. If you can upload a file that gets processed by the MSL coder (often triggered if the file extension is .msl or if the file content is sniffed as XML in a permissive environment), you win.
Here is the full Proof-of-Concept (PoC):
<?xml version="1.0" encoding="UTF-8"?>
<image>
<!--
The parser enters <image>, but hasn't allocated the internal
image structure yet because we haven't defined dimensions or read a file.
Then it hits <comment>.
-->
<comment>Goodbye, Server.</comment>
</image>When ImageMagick processes this:
<image>. The stack depth increases, but msl_info->image[0] remains NULL because no specific image data (read or new) has been invoked.<comment>Goodbye...</comment>.</comment>, it executes DeleteImageProperty(NULL, "comment").While a Denial of Service (DoS) might sound less sexy than Remote Code Execution (RCE), in modern cloud architectures, it can be devastating. Image processing is typically handled by asynchronous workers pulling jobs from a queue (e.g., Sidekiq, Celery, SQS).
Imagine an attacker uploads this malicious MSL file as a profile picture or an attachment. The worker picks up the job, attempts to process it, and crashes (segfault). The supervisor process (like Kubernetes or systemd) sees the crash and restarts the worker. The worker comes back online, checks the queue, picks up the same job, and crashes again.
This creates a "poison pill" scenario. A single 100-byte file can permanently jam an image processing pipeline, consuming compute resources in a restart loop and effectively taking down the service until the bad job is manually purged. If the system scales automatically based on CPU load (which spikes during crash/restart), you might even trigger an expensive auto-scaling event for nothing.
The immediate technical fix is to upgrade to Magick.NET 14.10.2 or the corresponding ImageMagick 7.x core release. This patches the coders/msl.c logic.
However, the strategic fix for security teams is to disable coders you don't use. ImageMagick supports hundreds of formats, many of which (like MSL, MVG, and XPS) are powerful scripting languages masquerading as image formats. These are historically prone to vulnerabilities.
Modify your policy.xml file to explicitly disable MSL if you aren't using it. This kills the entire attack class, not just this specific bug.
<!-- /etc/ImageMagick-7/policy.xml -->
<policymap>
<!-- ... other policies ... -->
<!-- DISABLE MSL SCRIPTING -->
<policy domain="coder" rights="none" pattern="MSL" />
</policymap>This is the digital equivalent of welding the window shut because you never open it anyway.
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:N/A:H| Product | Affected Versions | Fixed Version |
|---|---|---|
Magick.NET dlemstra | <= 14.10.1 | 14.10.2 |
ImageMagick ImageMagick Studio LLC | < 7.1.1-26 (Approximate) | 7.1.1-26 |
| Attribute | Detail |
|---|---|
| CWE ID | CWE-476 (NULL Pointer Dereference) |
| CVSS v3.1 | 6.5 (Medium) |
| Attack Vector | Network (AV:N) |
| Privileges Required | Low (PR:L) |
| Impact | Availability (A:H) |
| Exploit Status | PoC Available |
A NULL pointer dereference occurs when the application dereferences a pointer that it expects to be valid, but is NULL, typically causing a crash or exit.