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-25989
7.50.04%

Magick Tragic: The IEEE 754 Ghost in the Machine (CVE-2026-25989)

Alon Barad
Alon Barad
Software Engineer

Feb 24, 2026·5 min read·4 visits

PoC Available

Executive Summary (TL;DR)

ImageMagick failed to account for IEEE 754 rounding errors when casting doubles to integers. An attacker can provide an SVG with massive dimensions, bypassing a 'safety' check that uses a strict greater-than operator, leading to undefined behavior and a crash.

A high-severity Denial of Service vulnerability in ImageMagick caused by a fundamental misunderstanding of floating-point precision. By exploiting how doubles are cast to integers, attackers can crash the image processing pipeline using specially crafted SVG files.

The Hook: Infinite Improbability Drive

ImageMagick is the duct tape of the internet's visual layer. If you've ever uploaded a photo to a website and it magically resized itself, chances are ImageMagick was the invisible hand doing the work. It supports over 200 formats, from standard JPEGs to obscure vector formats like SVG. And that vast attack surface is exactly where things get messy.

CVE-2026-25989 isn't your standard buffer overflow or command injection. It's a subtle logic error deep in the math of the library—specifically, in how it handles the conversion of floating-point numbers to integers. It turns out that when you try to fit a massive number into a specific box, computers don't always do what you expect them to do.

This vulnerability is a Denial of Service (DoS) vector. While it (probably) won't let an attacker steal your database, it allows them to knock your image processing servers offline with a single, maliciously crafted SVG file. In the era of automated content pipelines, that's a recipe for a very bad day.

The Flaw: When Close Enough Isn't

To understand this bug, you need to remember how computers handle numbers. Integers are precise. 1 is 1. 18,446,744,073,709,551,615 (the max value for a 64-bit unsigned integer, or SIZE_MAX) is exactly that number. Floating-point numbers (doubles), however, are approximations based on scientific notation (IEEE 754). They trade precision for range.

A standard double has only 53 bits of mantissa (precision). SIZE_MAX requires 64 bits. When you cast SIZE_MAX to a double, the computer can't represent it exactly. It has to round. And in this specific case, it rounds up to the next representable value: $2^{64}$.

Here is the kicker: $2^{64}$ is technically larger than SIZE_MAX. If you try to cast that rounded double back into a size_t, you are asking the CPU to fit a number that is literally one too big into the register. This triggers Undefined Behavior (UB), which in C usually means the program screams and dies. ImageMagick tried to write a guard against this, but they trusted the math a little too much.

The Code: One Operator to Rule Them All

The vulnerability lived in MagickCore/image-private.h, inside inline helper functions designed to "safely" cast doubles. Let's look at the smoking gun in CastDoubleToSizeT.

The developers implemented a check to see if the input value was too big for the target integer type. They wrote this:

// The Vulnerable Logic
if (value > ((double) MAGICK_SIZE_MAX))
{
  errno=ERANGE;
  return(MAGICK_SIZE_MAX);
}
return((size_t) value);

Do you see the problem? It's the > (greater than) operator.

On a 64-bit system, ((double) MAGICK_SIZE_MAX) evaluates to $2^{64}$. If an attacker supplies a value that is exactly $2^{64}$, the condition 2^64 > 2^64 evaluates to FALSE. The code skips the error handling block and proceeds directly to return((size_t) value). The CPU attempts to cast $2^{64}$ to size_t, fails because it overflows, and the application crashes.

This is a classic off-by-one error, but in the floating-point domain. The fix was embarrassingly simple: change > to >=. If the value is equal to the max representable double, it's already too big.

The Exploit: Death by Vector Graphics

Exploiting this is trivial if you understand the file formats ImageMagick parses. Scalable Vector Graphics (SVG) are just XML text files that describe shapes. They allow you to define coordinates and dimensions using arbitrary numbers.

An attacker doesn't need to compile complex shellcode. They just need to open a text editor and write an SVG that defines a shape with a dimension that hits that magic floating-point boundary.

Here is a conceptual Proof-of-Concept (PoC):

<svg width="18446744073709551616" height="100" xmlns="http://www.w3.org/2000/svg">
  <!-- The width is exactly 2^64 -->
  <rect width="100%" height="100%" fill="red"/>
</svg>

When ImageMagick's msvg decoder reads this file, it parses the width attribute into a double. It passes that double to CastDoubleToSizeT to allocate memory or calculate offsets. The vulnerable check sees the number, thinks "Eh, it's not strictly greater than the max," and lets it through. The subsequent cast triggers a SIGFPE (Floating Point Exception) or a SIGSEGV (Segmentation Fault), killing the process instantly.

The Fix: A Greater Than or Equal Solution

The patch provided by the maintainer, Cristy, in commit 5a545ab9d6c3d12a6a76cfed32b87df096729d95, is a textbook one-character fix. It acknowledges the reality of IEEE 754 rounding behavior.

--- a/MagickCore/image-private.h
+++ b/MagickCore/image-private.h
@@ -123,7 +123,7 @@
 static inline size_t CastDoubleToSizeT(const double x)
 {
   // ... snippets ...
-  if (value > ((double) MAGICK_SIZE_MAX))
+  if (value >= ((double) MAGICK_SIZE_MAX))
     {
       errno=ERANGE;
       return(MAGICK_SIZE_MAX);

By using the >= operator, the code now correctly catches cases where the input value has been rounded up to the unrepresentable $2^{64}$ boundary. Instead of crashing, the function now safely saturates the value to MAGICK_SIZE_MAX and sets the error flag ERANGE. This prevents the undefined behavior and keeps the application running, likely just rendering a weirdly large image or returning a controlled error.

Official Patches

ImageMagickGitHub Commit fixing the issue
GitHubOfficial GitHub Security Advisory

Fix Analysis (1)

Technical Appendix

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

Affected Systems

ImageMagick < 7.1.2-15ImageMagick < 6.9.13-40Magick.NET < 14.10.3Web applications handling user-uploaded SVGs

Affected Versions Detail

Product
Affected Versions
Fixed Version
ImageMagick
ImageMagick Studio LLC
< 6.9.13-406.9.13-40
ImageMagick
ImageMagick Studio LLC
>= 7.0.0-0, < 7.1.2-157.1.2-15
Magick.NET
dlemstra
< 14.10.314.10.3
AttributeDetail
CWE IDCWE-193 (Off-by-one Error)
CVSS7.5 (High)
Attack VectorNetwork (Image Upload)
ImpactDenial of Service (Crash)
KEV StatusNot Listed
Patch Commit5a545ab9d6c3d12a6a76cfed32b87df096729d95

MITRE ATT&CK Mapping

T1499Endpoint Denial of Service
Impact
T1203Exploitation for Client Execution
Execution
CWE-193
Off-by-one Error

Vulnerability Timeline

Fix committed to ImageMagick repository
2026-02-07
GHSA-7355-pwx2-pm84 Published
2026-02-24
Magick.NET patch released
2026-02-24

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.