Feb 24, 2026·5 min read·39 visits
ImageMagick has a feature to limit JPEG file size by brute-forcing quality settings. A logic error meant that if the encoder hiccuped (returned false), the loop would retry without changing parameters—forever. Update to 7.1.2-15 or 6.9.13-40 immediately.
A critical Denial of Service (DoS) vulnerability in ImageMagick's JPEG encoder allows attackers to trigger an infinite loop by abusing the `jpeg:extent` feature. By forcing a write failure during the file-size optimization process, the application enters a CPU-exhausting cycle that hangs the process indefinitely.
ImageMagick is the duct tape of the internet. If you upload a profile picture to a website, chances are some backend script is piping it through magick before it hits an S3 bucket. One of its handier, albeit computationally expensive, features is the jpeg:extent define.
This feature allows a user to say, "I don't care about the quality, just make sure this JPEG is under 50KB." Since JPEG compression isn't linear, ImageMagick can't just calculate the perfect quality setting mathematically. Instead, it does what computers do best: it guesses.
It implements a binary search, repeatedly encoding the image at different quality levels (0-100) until it finds the highest quality that fits within the target file size. It’s a brute-force optimization loop running inside your image processor. And as we know, loops are where the demons live.
A robust binary search needs three things: a lower bound, an upper bound, and a way to exit. In coders/jpeg.c, ImageMagick sets up this search loop to iterate through quality settings. Inside the loop, it calls WriteJPEGImage to generate a candidate image, checks its size, and adjusts the bounds accordingly.
But what happens if WriteJPEGImage fails? Not because the image is too big, but because of a resource error, an I/O glitch, or a library hiccup? The function returns MagickFalse.
The developers handled this error condition with a single instruction: continue.
Here lies the logic bomb. In a for loop, continue jumps to the increment step. But this was a while loop logic where the bounds (minimum/maximum quality) were only updated after a successful write. By hitting continue, the code skipped the logic that changes the loop state. It essentially said: "That failed. Let's try the exact same thing, with the exact same parameters, again."
It is the literal definition of insanity: doing the same thing over and over and expecting a different result. The process spins at 100% CPU, trying to encode a ghost image until the heat death of the universe or a sysadmin kill -9s it.
Let's look at the "smoking gun" in coders/jpeg.c. This is a classic example of how a single control flow statement can sink a battleship.
Vulnerable Logic (Simplified):
/* coders/jpeg.c before patch */
while (minimum <= maximum) {
// ... setup logic ...
status = WriteJPEGImage(extent_info, jpeg_image, exception);
if (status == MagickFalse)
continue; // <--- THE KILLER. Re-loops without changing state.
// The code below is unreachable if status is false
if (GetBlobSize(jpeg_image) <= extent)
minimum = jpeg_image->quality + 1;
else
maximum = jpeg_image->quality - 1;
}The fix was embarrassingly simple. If the write fails, stop trying to optimize. Abort the loop.
The Fix:
- if (status == MagickFalse)
- continue;
+ if (status == MagickFalse)
+ break;By changing continue to break, the loop terminates upon failure, returning control (and the error) to the caller rather than entering an infinite spin cycle.
To weaponize this, an attacker needs two ingredients: access to pass the jpeg:extent parameter (often exposed in resizing APIs) and a way to make WriteJPEGImage fail consistently inside that loop.
WriteJPEGImage can fail for various reasons:
An attacker targeting a web service that uses ImageMagick (e.g., convert input.jpg -define jpeg:extent=50kb output.jpg) could try to flood the service with requests. If they can trigger a condition where the temporary file creation inside the loop fails, the service enters a zombie state. Send enough of these, and you starve the server's CPU cores one by one until the load average hits the stratosphere.
This is a pure Availability vulnerability. There is no Remote Code Execution (RCE) here, and you aren't stealing database credentials. However, in the world of cloud computing, CPU cycles equal money, and availability equals trust.
A single malicious request can permanently peg a CPU core. If your server processes images on 4 cores, it only takes 4 requests to completely lock up the service. Because the loop is tight (CPU-bound), it doesn't wait for I/O, meaning it generates maximum heat and maximum lag.
For auto-scaling cloud groups, this is particularly nasty. The high CPU usage might trigger your auto-scaler to spin up more instances. The attacker continues to send requests, locking those up too. Essentially, this vulnerability allows an attacker to financially DoS you by forcing you to pay for a fleet of servers doing absolutely nothing but failing to compress a JPEG.
The remediation is straightforward: update your libraries. The patch exists in ImageMagick 7.1.2-15 and 6.9.13-40. If you are using .NET, pull the latest Magick.NET (14.10.3).
If you cannot patch immediately, you must sanitize your inputs. If your application allows users to pass arbitrary arguments to ImageMagick (which is a terrible idea for many other reasons), block the jpeg:extent define.
Detection:
Monitor your infrastructure for processes named magick or convert that have high CPU time but aren't exiting. A process running for 5+ minutes at 99% CPU is a strong indicator that you've hit this loop.
CVSS:3.1/AV:L/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H| Product | Affected Versions | Fixed Version |
|---|---|---|
ImageMagick ImageMagick | < 7.1.2-15 | 7.1.2-15 |
ImageMagick (Legacy) ImageMagick | < 6.9.13-40 | 6.9.13-40 |
Magick.NET dlemstra | < 14.10.3 | 14.10.3 |
| Attribute | Detail |
|---|---|
| CWE ID | CWE-835 |
| Attack Vector | Local / Context-Dependent |
| CVSS Score | 6.2 |
| Impact | High (Availability) |
| Exploit Status | PoC Pending |
| Patch Date | 2026-02-13 |
Loop with Unreachable Exit Condition ('Infinite Loop')
A directory traversal vulnerability exists in the Microsoft .NET System.Formats.Tar library during archive extraction. When extracting a TAR archive using the TarFile.ExtractToDirectory API, the extraction engine improperly resolves symbolic links prior to file creation, allowing local unauthorized attackers to write or overwrite arbitrary files outside the target directory. This can lead to local tampering, privilege escalation, or arbitrary code execution.
A client-side HTML sanitization bypass vulnerability exists in the Bleach library where the formaction attribute is not recognized as a URI. This allows attackers to inject javascript: URIs when formaction is on the allowed list, resulting in Cross-Site Scripting (XSS).
A reflected DOM-based Cross-Site Scripting (XSS) vulnerability was identified in Nuxt's core <NuxtLink> component. Prior to the patched versions, the component failed to validate or sanitize the target URI schemes before directly rendering them into the 'href' attribute of native HTML anchor elements. An attacker who controls the input bound to the 'to' or 'href' properties can inject executable URI schemes, such as 'javascript:' or 'data:', leading to arbitrary script execution in the context of the user's browser session.
A state persistence vulnerability exists in Tornado's CurlAsyncHTTPClient component where pooled pycurl.Curl handles are reused across asynchronous requests without a complete state reset. Consequently, sensitive per-request configurations, such as client TLS certificates or proxy basic authentication credentials, persist on the shared handle. This behavior leads to subsequent requests leaking these credentials to unauthorized remote servers.
CVE-2026-48748 is a denial-of-service vulnerability in Netty's HTTP/3 codec (netty-codec-http3) occurring when QPACK dynamic tables are enabled but the blocked streams limit is not explicitly configured. A bug in limit checking and a memory leak in stream tracking allow unauthenticated remote attackers to exhaust the JVM heap memory and crash the server.
CVE-2026-50009 is a cryptographic design vulnerability in the Netty network application framework. Prior to version 4.2.15.Final, the framework's QUIC protocol implementation fails to cryptographically segregate the generated Connection IDs and the associated Stateless Reset Tokens. An on-path network attacker who sniffs traffic during a Connection ID rotation can extract secret token material from cleartext headers, enabling them to inject spoofed reset packets and terminate active connections.