The vulnerability is a heap-buffer-overflow in the InterpretImageFilename function within ImageMagick, as detailed in the provided crash analysis and security advisory. The root cause is an off-by-one error when parsing format strings containing a double percent sign ('%%'). The provided patches from both the main ImageMagick and the ImageMagick6 repositories clearly show the fix. The vulnerable code incorrectly incremented a pointer, causing a read beyond the allocated buffer on the next loop iteration. The fix adjusts the pointer increment to prevent this out-of-bounds access. The AddressSanitizer output confirms the crash occurs within InterpretImageFilename at MagickCore/image.c:1674, directly pointing to the vulnerable function. The provided commits fix this exact line of code. Therefore, the InterpretImageFilename function is the identified vulnerable function.
| Package Name | Ecosystem | Vulnerable Versions | First Patched Version |
|---|---|---|---|
| Magick.NET-Q16-AnyCPU | nuget | < 14.7.0 | 14.7.0 |
| Magick.NET-Q16-HDRI-AnyCPU | nuget | < 14.7.0 | 14.7.0 |
| Magick.NET-Q16-HDRI-OpenMP-arm64 | nuget | < 14.7.0 | 14.7.0 |
| Magick.NET-Q16-HDRI-OpenMP-x64 | nuget | < 14.7.0 | 14.7.0 |
| Magick.NET-Q16-HDRI-arm64 | nuget | < 14.7.0 | 14.7.0 |
| Magick.NET-Q16-HDRI-x64 | nuget | < 14.7.0 | 14.7.0 |
| Magick.NET-Q16-HDRI-x86 | nuget | < 14.7.0 | 14.7.0 |
| Magick.NET-Q16-OpenMP-arm64 | nuget | < 14.7.0 | 14.7.0 |
| Magick.NET-Q16-OpenMP-x64 | nuget | < 14.7.0 | 14.7.0 |
| Magick.NET-Q16-arm64 | nuget | < 14.7.0 | 14.7.0 |
| Magick.NET-Q16-x64 | nuget | < 14.7.0 | 14.7.0 |
| Magick.NET-Q16-x86 | nuget | < 14.7.0 | 14.7.0 |
| Magick.NET-Q8-AnyCPU | nuget | < 14.7.0 | 14.7.0 |
| Magick.NET-Q8-OpenMP-arm64 | nuget | < 14.7.0 | 14.7.0 |
| Magick.NET-Q8-OpenMP-x64 | nuget | < 14.7.0 | 14.7.0 |
| Magick.NET-Q8-arm64 | nuget | < 14.7.0 | 14.7.0 |
| Magick.NET-Q8-x64 | nuget | < 14.7.0 | 14.7.0 |
| Magick.NET-Q8-x86 | nuget | < 14.7.0 | 14.7.0 |
The first command line argument is interpreted as MagickImageCommand:
https://github.com/ImageMagick/ImageMagick/blob/8fff9b4f44d2e8b5cae2bd6db70930a144d15f12/utilities/magick.c#L83
const CommandInfo
MagickCommands[] =
{
MagickCommandSize("magick", MagickFalse, MagickImageCommand),
It is invoked here: https://github.com/ImageMagick/ImageMagick/blob/8fff9b4f44d2e8b5cae2bd6db70930a144d15f12/MagickWand/magick-cli.c#L220
status=command(image_info,argc,argv,&text,exception);
The execution then follows this path:
The execution eventually reaches InterpretImageFilename and enters a loop. The format variable here is "%%". At this point, it is safe to access *(format + 2) but not safe to access *(format + 3).
for (p=strchr(format,'%'); p != (char *) NULL; p=strchr(p+1,'%'))
{
q=(char *) p+1;
if (*q == '%')
{
p=q+1;
continue;
}
The first strchr call returns a pointer equal to format and assigns it to p. Then q is initialized with p + 1 (format + 1), and *q is '%', so the code enters the if branch. Here, p is reassigned to q + 1 (format + 2).
In the next iteration, p + 1 (format + 3) is passed to strchr, and when strchr accesses it, this causes an out-of-bounds read.
Ongoing coverage of React2Shell