ghsa-qh3h-j545-h8c9
Vulnerability from github
Hi, we have found a stack buffer overflow and would like to report this issue. Could you confirm if this qualifies as a security vulnerability? I am happy to provide any additional information needed.
Summary
In ImageMagick's magick mogrify command, specifying multiple consecutive %d format specifiers in a filename template causes internal pointer arithmetic to generate an address below the beginning of the stack buffer, resulting in a stack overflow through vsnprintf().
Additional information
Upon further investigation, we found that the same issue occurs not only with mogrify but also with the following subcommands: compare, composite, conjure, convert, identify, mogrify, and montage.
Furthermore, we confirmed that this vulnerability has the potential to lead to RCE. RCE is possible when ASLR is disabled and there is a suitable one_gadget in libc, provided that options and filenames can be controlled.
Details
- Vulnerability Type: CWE-124: Buffer Underwrite
- Affected Component: MagickCore/image.c - Format processing within InterpretImageFilename()
- Affected Version: ImageMagick 7.1.1-47 (as of commit 82572afc, June 2025)
- CWE-124: Buffer Underwrite: A vulnerability where writing occurs to memory addresses before the beginning of a buffer. This is caused by a design flaw in fixed offset correction, resulting in negative pointer arithmetic during consecutive format specifier processing.
Reproduction
Tested Environment
- Operating System: Ubuntu 22.04 LTS
- Architecture: x86_64
- Compiler: gcc with AddressSanitizer (gcc version: 11.4.0)
Reproduction Steps
```bash
Clone source
git clone --depth 1 --branch 7.1.1-47 https://github.com/ImageMagick/ImageMagick.git ImageMagick-7.1.1 cd ImageMagick-7.1.1
Build with ASan
CFLAGS="-g -O0 -fsanitize=address -fno-omit-frame-pointer" CXXFLAGS="$CFLAGS" LDFLAGS="-fsanitize=address" ./configure --enable-maintainer-mode --enable-shared && make -j$(nproc) && make install
Trigger crash
./utilities/magick mogrify %d%d ```
Output
```plaintext ==4155==ERROR: AddressSanitizer: stack-buffer-overflow on address 0x7ffda834caae at pc 0x7f1ea367fb27 bp 0x7ffda834b680 sp 0x7ffda834ae10 WRITE of size 2 at 0x7ffda834caae thread T0 #0 0x7f1ea367fb26 in __interceptor_vsnprintf ../../../../src/libsanitizer/sanitizer_common/sanitizer_common_interceptors.inc:1668 #1 0x7f1ea2dc9e3e in FormatLocaleStringList MagickCore/locale.c:470 #2 0x7f1ea2dc9fd9 in FormatLocaleString MagickCore/locale.c:495 #3 0x7f1ea2da0ad5 in InterpretImageFilename MagickCore/image.c:1696 #4 0x7f1ea2c6126b in ReadImages MagickCore/constitute.c:1051 #5 0x7f1ea27ef29b in MogrifyImageCommand MagickWand/mogrify.c:3858 #6 0x7f1ea278e95d in MagickCommandGenesis MagickWand/magick-cli.c:177 #7 0x560813499a0c in MagickMain utilities/magick.c:153 #8 0x560813499cba in main utilities/magick.c:184 #9 0x7f1ea1c0bd8f in __libc_start_call_main ../sysdeps/nptl/libc_start_call_main.h:58 #10 0x7f1ea1c0be3f in __libc_start_main_impl ../csu/libc-start.c:392 #11 0x560813499404 in _start (/root/workdir/ImageMagick/utilities/.libs/magick+0x2404)
Address 0x7ffda834caae is located in stack of thread T0 at offset 62 in frame #0 0x7f1ea2c60f62 in ReadImages MagickCore/constitute.c:1027
This frame has 2 object(s): [32, 40) 'images' (line 1033) [64, 4160) 'read_filename' (line 1029) <== Memory access at offset 62 underflows this variable HINT: this may be a false positive if your program uses some custom stack unwind mechanism, swapcontext or vfork (longjmp and C++ exceptions are supported) SUMMARY: AddressSanitizer: stack-buffer-overflow ../../../../src/libsanitizer/sanitizer_common/sanitizer_common_interceptors.inc:1668 in __interceptor_vsnprintf Shadow bytes around the buggy address: 0x100035061900: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x100035061910: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x100035061920: 00 00 00 00 00 00 00 00 f3 f3 f3 f3 f3 f3 f3 f3 0x100035061930: f3 f3 f3 f3 f3 f3 f3 f3 00 00 00 00 00 00 00 00 0x100035061940: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 =>0x100035061950: f1 f1 00 f2 f2[f2]00 00 00 00 00 00 00 00 00 00 0x100035061960: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x100035061970: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x100035061980: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x100035061990: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x1000350619a0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 Shadow byte legend (one shadow byte represents 8 application bytes): Addressable: 00 Partially addressable: 01 02 03 04 05 06 07 Heap left redzone: fa Freed heap region: fd Stack left redzone: f1 Stack mid redzone: f2 Stack right redzone: f3 Stack after return: f5 Stack use after scope: f8 Global redzone: f9 Global init order: f6 Poisoned by user: f7 Container overflow: fc Array cookie: ac Intra object redzone: bb ASan internal: fe Left alloca redzone: ca Right alloca redzone: cb Shadow gap: cc ==4155==ABORTING ```
Affected Code
In MagickCore/image.c, within the InterpretImageFilename() function:
c
MagickExport size_t InterpretImageFilename(const ImageInfo *image_info,
Image *image,const char *format,int value,char *filename,
ExceptionInfo *exception)
{
...
for (p=strchr(format,'%'); p != (char *) NULL; p=strchr(p+1,'%'))
{
q=(char *) p+1;
if (*q == '%')
{
p=q+1;
continue;
}
field_width=0;
if (*q == '0')
field_width=(ssize_t) strtol(q,&q,10);
switch (*q)
{
case 'd':
case 'o':
case 'x':
{
q++;
c=(*q);
*q='\0';
/*--------Affected--------*/
(void) FormatLocaleString(filename+(p-format-offset),(size_t)
(MagickPathExtent-(p-format-offset)),p,value);
offset+=(4-field_width);
/*--------Affected--------*/
*q=c;
(void) ConcatenateMagickString(filename,q,MagickPathExtent);
canonical=MagickTrue;
if (*(q-1) != '%')
break;
p++;
break;
}
case '[':
{
...
}
default:
break;
}
}
Technical Analysis
This vulnerability is caused by an inconsistency in the template expansion processing within InterpretImageFilename().
The format specifiers %d, %o, and %x in templates are replaced with integer values by FormatLocaleString(), but the output buffer position is calculated by filename + (p - format - offset).
The offset variable is cumulatively incremented to correct the output length of %d etc., but the design using a static offset += (4 - field_width) causes offset to increase excessively when % specifiers are consecutive in the template, creating a dangerous state where the write destination address points before filename.
The constant 4 was likely chosen based on the character count of typical format specifiers like %03d (total of 4 characters: %, 0, 3, d). However, in reality, there are formats with only 2 characters like %d, and formats with longer width specifications (e.g., %010d), so this uniform constant-based correction is inconsistent with actual template structures.
As a result, when the correction value becomes excessive, offset exceeds the relative position p - format within the template, generating a negative index. This static and template-independent design of the correction processing is the root cause of this vulnerability.
This causes vsnprintf() to write outside the stack buffer range, which is detected by AddressSanitizer as a stack-buffer-overflow.
Proposed Fix
In MagickCore/image.c, within the InterpretImageFilename() function:
c
MagickExport size_t InterpretImageFilename(const ImageInfo *image_info,
Image *image,const char *format,int value,char *filename,
ExceptionInfo *exception)
{
...
/*--------Changed--------*/
ssize_t
field_width,
offset,
written; // Added
/*--------Changed--------*/
...
for (p=strchr(format,'%'); p != (char *) NULL; p=strchr(p+1,'%'))
{
q=(char *) p+1;
if (*q == '%')
{
p=q+1;
continue;
}
field_width=0;
if (*q == '0')
field_width=(ssize_t) strtol(q,&q,10);
switch (*q)
{
case 'd':
case 'o':
case 'x':
{
q++;
c=(*q);
*q='\0';
written = FormatLocaleString(filename+(p-format-offset),(size_t)
(MagickPathExtent-(p-format-offset)),p,value);
/*--------Changed--------*/
if (written <= 0 || written > (MagickPathExtent - (p - format - offset)))
return 0;
offset += (ssize_t)((q - p) - written);
/*--------Changed--------*/
*q=c;
(void) ConcatenateMagickString(filename,q,MagickPathExtent);
canonical=MagickTrue;
if (*(q-1) != '%')
break;
p++;
break;
}
case '[':
{
...
}
default:
break;
}
}
- By updating offset based on the difference between template description length (q - p) and the number of output bytes written, buffer position consistency is maintained.
- Correction is performed according to the actual template structure, ensuring stable behavior regardless of format length without relying on static constants.
- Range checking of written allows detection of vsnprintf failures and excessive writes.
Commits
Fixed in https://github.com/ImageMagick/ImageMagick/commit/66dc8f51c11b0ae1f1cdeacd381c3e9a4de69774 and https://github.com/ImageMagick/ImageMagick6/commit/643deeb60803488373cd4799b24d5786af90972e
{
"affected": [
{
"package": {
"ecosystem": "NuGet",
"name": "Magick.NET-Q16-AnyCPU"
},
"ranges": [
{
"events": [
{
"introduced": "0"
},
{
"fixed": "14.7.0"
}
],
"type": "ECOSYSTEM"
}
]
},
{
"package": {
"ecosystem": "NuGet",
"name": "Magick.NET-Q16-HDRI-AnyCPU"
},
"ranges": [
{
"events": [
{
"introduced": "0"
},
{
"fixed": "14.7.0"
}
],
"type": "ECOSYSTEM"
}
]
},
{
"package": {
"ecosystem": "NuGet",
"name": "Magick.NET-Q16-HDRI-OpenMP-arm64"
},
"ranges": [
{
"events": [
{
"introduced": "0"
},
{
"fixed": "14.7.0"
}
],
"type": "ECOSYSTEM"
}
]
},
{
"package": {
"ecosystem": "NuGet",
"name": "Magick.NET-Q16-HDRI-OpenMP-x64"
},
"ranges": [
{
"events": [
{
"introduced": "0"
},
{
"fixed": "14.7.0"
}
],
"type": "ECOSYSTEM"
}
]
},
{
"package": {
"ecosystem": "NuGet",
"name": "Magick.NET-Q16-HDRI-arm64"
},
"ranges": [
{
"events": [
{
"introduced": "0"
},
{
"fixed": "14.7.0"
}
],
"type": "ECOSYSTEM"
}
]
},
{
"package": {
"ecosystem": "NuGet",
"name": "Magick.NET-Q16-HDRI-x64"
},
"ranges": [
{
"events": [
{
"introduced": "0"
},
{
"fixed": "14.7.0"
}
],
"type": "ECOSYSTEM"
}
]
},
{
"package": {
"ecosystem": "NuGet",
"name": "Magick.NET-Q16-HDRI-x86"
},
"ranges": [
{
"events": [
{
"introduced": "0"
},
{
"fixed": "14.7.0"
}
],
"type": "ECOSYSTEM"
}
]
},
{
"package": {
"ecosystem": "NuGet",
"name": "Magick.NET-Q16-OpenMP-arm64"
},
"ranges": [
{
"events": [
{
"introduced": "0"
},
{
"fixed": "14.7.0"
}
],
"type": "ECOSYSTEM"
}
]
},
{
"package": {
"ecosystem": "NuGet",
"name": "Magick.NET-Q16-OpenMP-x64"
},
"ranges": [
{
"events": [
{
"introduced": "0"
},
{
"fixed": "14.7.0"
}
],
"type": "ECOSYSTEM"
}
]
},
{
"package": {
"ecosystem": "NuGet",
"name": "Magick.NET-Q16-arm64"
},
"ranges": [
{
"events": [
{
"introduced": "0"
},
{
"fixed": "14.7.0"
}
],
"type": "ECOSYSTEM"
}
]
},
{
"package": {
"ecosystem": "NuGet",
"name": "Magick.NET-Q16-x64"
},
"ranges": [
{
"events": [
{
"introduced": "0"
},
{
"fixed": "14.7.0"
}
],
"type": "ECOSYSTEM"
}
]
},
{
"package": {
"ecosystem": "NuGet",
"name": "Magick.NET-Q16-x86"
},
"ranges": [
{
"events": [
{
"introduced": "0"
},
{
"fixed": "14.7.0"
}
],
"type": "ECOSYSTEM"
}
]
},
{
"package": {
"ecosystem": "NuGet",
"name": "Magick.NET-Q8-AnyCPU"
},
"ranges": [
{
"events": [
{
"introduced": "0"
},
{
"fixed": "14.7.0"
}
],
"type": "ECOSYSTEM"
}
]
},
{
"package": {
"ecosystem": "NuGet",
"name": "Magick.NET-Q8-OpenMP-arm64"
},
"ranges": [
{
"events": [
{
"introduced": "0"
},
{
"fixed": "14.7.0"
}
],
"type": "ECOSYSTEM"
}
]
},
{
"package": {
"ecosystem": "NuGet",
"name": "Magick.NET-Q8-OpenMP-x64"
},
"ranges": [
{
"events": [
{
"introduced": "0"
},
{
"fixed": "14.7.0"
}
],
"type": "ECOSYSTEM"
}
]
},
{
"package": {
"ecosystem": "NuGet",
"name": "Magick.NET-Q8-arm64"
},
"ranges": [
{
"events": [
{
"introduced": "0"
},
{
"fixed": "14.7.0"
}
],
"type": "ECOSYSTEM"
}
]
},
{
"package": {
"ecosystem": "NuGet",
"name": "Magick.NET-Q8-x64"
},
"ranges": [
{
"events": [
{
"introduced": "0"
},
{
"fixed": "14.7.0"
}
],
"type": "ECOSYSTEM"
}
]
},
{
"package": {
"ecosystem": "NuGet",
"name": "Magick.NET-Q8-x86"
},
"ranges": [
{
"events": [
{
"introduced": "0"
},
{
"fixed": "14.7.0"
}
],
"type": "ECOSYSTEM"
}
]
}
],
"aliases": [
"CVE-2025-53101"
],
"database_specific": {
"cwe_ids": [
"CWE-124"
],
"github_reviewed": true,
"github_reviewed_at": "2025-08-25T15:43:37Z",
"nvd_published_at": "2025-07-14T20:15:29Z",
"severity": "HIGH"
},
"details": "Hi, we have found a stack buffer overflow and would like to report this issue.\nCould you confirm if this qualifies as a security vulnerability? I am happy to provide any additional information needed.\n\n## Summary\n\nIn ImageMagick\u0027s `magick mogrify` command, specifying multiple consecutive `%d` format specifiers in a filename template causes internal pointer arithmetic to generate an address below the beginning of the stack buffer, resulting in a stack overflow through `vsnprintf()`.\n\n### Additional information\n\n Upon further investigation, we found that the same issue occurs not only with mogrify but also with the following subcommands: compare, composite, conjure, convert, identify, mogrify, and montage.\n\nFurthermore, we confirmed that this vulnerability has the potential to lead to RCE. RCE is possible when ASLR is disabled and there is a suitable one_gadget in libc, provided that options and filenames can be controlled.\n\n## Details\n\n- **Vulnerability Type:** CWE-124: Buffer Underwrite\n- **Affected Component:** MagickCore/image.c - Format processing within InterpretImageFilename()\n- **Affected Version:** ImageMagick 7.1.1-47 (as of commit 82572afc, June 2025)\n- **CWE-124: Buffer Underwrite:** A vulnerability where writing occurs to memory addresses before the beginning of a buffer. This is caused by a design flaw in fixed offset correction, resulting in negative pointer arithmetic during consecutive format specifier processing.\n\n## Reproduction\n\n### Tested Environment\n\n- **Operating System:** Ubuntu 22.04 LTS\n- **Architecture:** x86_64\n- **Compiler:** gcc with AddressSanitizer (gcc version: 11.4.0)\n\n### Reproduction Steps\n\n```bash\n# Clone source\ngit clone --depth 1 --branch 7.1.1-47 https://github.com/ImageMagick/ImageMagick.git ImageMagick-7.1.1\ncd ImageMagick-7.1.1\n\n# Build with ASan\nCFLAGS=\"-g -O0 -fsanitize=address -fno-omit-frame-pointer\" CXXFLAGS=\"$CFLAGS\" LDFLAGS=\"-fsanitize=address\" ./configure --enable-maintainer-mode --enable-shared \u0026\u0026 make -j$(nproc) \u0026\u0026 make install\n\n# Trigger crash\n./utilities/magick mogrify %d%d\n```\n\n### Output\n\n```plaintext\n==4155==ERROR: AddressSanitizer: stack-buffer-overflow on address 0x7ffda834caae at pc 0x7f1ea367fb27 bp 0x7ffda834b680 sp 0x7ffda834ae10\nWRITE of size 2 at 0x7ffda834caae thread T0\n #0 0x7f1ea367fb26 in __interceptor_vsnprintf ../../../../src/libsanitizer/sanitizer_common/sanitizer_common_interceptors.inc:1668\n #1 0x7f1ea2dc9e3e in FormatLocaleStringList MagickCore/locale.c:470\n #2 0x7f1ea2dc9fd9 in FormatLocaleString MagickCore/locale.c:495\n #3 0x7f1ea2da0ad5 in InterpretImageFilename MagickCore/image.c:1696\n #4 0x7f1ea2c6126b in ReadImages MagickCore/constitute.c:1051\n #5 0x7f1ea27ef29b in MogrifyImageCommand MagickWand/mogrify.c:3858\n #6 0x7f1ea278e95d in MagickCommandGenesis MagickWand/magick-cli.c:177\n #7 0x560813499a0c in MagickMain utilities/magick.c:153\n #8 0x560813499cba in main utilities/magick.c:184\n #9 0x7f1ea1c0bd8f in __libc_start_call_main ../sysdeps/nptl/libc_start_call_main.h:58\n #10 0x7f1ea1c0be3f in __libc_start_main_impl ../csu/libc-start.c:392\n #11 0x560813499404 in _start (/root/workdir/ImageMagick/utilities/.libs/magick+0x2404)\n\nAddress 0x7ffda834caae is located in stack of thread T0 at offset 62 in frame\n #0 0x7f1ea2c60f62 in ReadImages MagickCore/constitute.c:1027\n\n This frame has 2 object(s):\n [32, 40) \u0027images\u0027 (line 1033)\n [64, 4160) \u0027read_filename\u0027 (line 1029) \u003c== Memory access at offset 62 underflows this variable\nHINT: this may be a false positive if your program uses some custom stack unwind mechanism, swapcontext or vfork\n (longjmp and C++ exceptions *are* supported)\nSUMMARY: AddressSanitizer: stack-buffer-overflow ../../../../src/libsanitizer/sanitizer_common/sanitizer_common_interceptors.inc:1668 in __interceptor_vsnprintf\nShadow bytes around the buggy address:\n 0x100035061900: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00\n 0x100035061910: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00\n 0x100035061920: 00 00 00 00 00 00 00 00 f3 f3 f3 f3 f3 f3 f3 f3\n 0x100035061930: f3 f3 f3 f3 f3 f3 f3 f3 00 00 00 00 00 00 00 00\n 0x100035061940: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00\n=\u003e0x100035061950: f1 f1 00 f2 f2[f2]00 00 00 00 00 00 00 00 00 00\n 0x100035061960: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00\n 0x100035061970: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00\n 0x100035061980: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00\n 0x100035061990: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00\n 0x1000350619a0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00\nShadow byte legend (one shadow byte represents 8 application bytes):\n Addressable: 00\n Partially addressable: 01 02 03 04 05 06 07 \n Heap left redzone: fa\n Freed heap region: fd\n Stack left redzone: f1\n Stack mid redzone: f2\n Stack right redzone: f3\n Stack after return: f5\n Stack use after scope: f8\n Global redzone: f9\n Global init order: f6\n Poisoned by user: f7\n Container overflow: fc\n Array cookie: ac\n Intra object redzone: bb\n ASan internal: fe\n Left alloca redzone: ca\n Right alloca redzone: cb\n Shadow gap: cc\n==4155==ABORTING\n```\n\n### Affected Code\n\nIn `MagickCore/image.c`, within the `InterpretImageFilename()` function:\n\n```c\nMagickExport size_t InterpretImageFilename(const ImageInfo *image_info,\n Image *image,const char *format,int value,char *filename,\n ExceptionInfo *exception)\n{\n...\n for (p=strchr(format,\u0027%\u0027); p != (char *) NULL; p=strchr(p+1,\u0027%\u0027))\n {\n q=(char *) p+1;\n if (*q == \u0027%\u0027)\n {\n p=q+1;\n continue;\n }\n field_width=0;\n if (*q == \u00270\u0027)\n field_width=(ssize_t) strtol(q,\u0026q,10);\n switch (*q)\n {\n case \u0027d\u0027:\n case \u0027o\u0027:\n case \u0027x\u0027:\n {\n q++;\n c=(*q);\n *q=\u0027\\0\u0027;\n /*--------Affected--------*/\n (void) FormatLocaleString(filename+(p-format-offset),(size_t)\n (MagickPathExtent-(p-format-offset)),p,value);\n offset+=(4-field_width);\n /*--------Affected--------*/\n *q=c;\n (void) ConcatenateMagickString(filename,q,MagickPathExtent);\n canonical=MagickTrue;\n if (*(q-1) != \u0027%\u0027)\n break;\n p++;\n break;\n }\n case \u0027[\u0027:\n {\n ...\n }\n default:\n break;\n }\n }\n```\n\n## Technical Analysis\n\nThis vulnerability is caused by an inconsistency in the template expansion processing within `InterpretImageFilename()`.\n\nThe format specifiers `%d`, `%o`, and `%x` in templates are replaced with integer values by `FormatLocaleString()`, but the output buffer position is calculated by `filename + (p - format - offset)`.\n\nThe `offset` variable is cumulatively incremented to correct the output length of `%d` etc., but the design using a static `offset += (4 - field_width)` causes `offset` to increase excessively when `%` specifiers are consecutive in the template, creating a dangerous state where the write destination address points before `filename`.\n\nThe constant `4` was likely chosen based on the character count of typical format specifiers like `%03d` (total of 4 characters: `%`, `0`, `3`, `d`). However, in reality, there are formats with only 2 characters like `%d`, and formats with longer width specifications (e.g., `%010d`), so this uniform constant-based correction is inconsistent with actual template structures.\n\nAs a result, when the correction value becomes excessive, `offset` exceeds the relative position `p - format` within the template, generating a negative index. This static and template-independent design of the correction processing is the root cause of this vulnerability.\n\nThis causes `vsnprintf()` to write outside the stack buffer range, which is detected by AddressSanitizer as a `stack-buffer-overflow`.\n\n## Proposed Fix\n\nIn `MagickCore/image.c`, within the `InterpretImageFilename()` function:\n\n```c\nMagickExport size_t InterpretImageFilename(const ImageInfo *image_info,\n Image *image,const char *format,int value,char *filename,\n ExceptionInfo *exception)\n{\n...\n /*--------Changed--------*/\n ssize_t\n field_width,\n offset,\n written; // Added\n /*--------Changed--------*/\n...\n for (p=strchr(format,\u0027%\u0027); p != (char *) NULL; p=strchr(p+1,\u0027%\u0027))\n {\n q=(char *) p+1;\n if (*q == \u0027%\u0027)\n {\n p=q+1;\n continue;\n }\n field_width=0;\n if (*q == \u00270\u0027)\n field_width=(ssize_t) strtol(q,\u0026q,10);\n switch (*q)\n {\n case \u0027d\u0027:\n case \u0027o\u0027:\n case \u0027x\u0027:\n {\n q++;\n c=(*q);\n *q=\u0027\\0\u0027;\n written = FormatLocaleString(filename+(p-format-offset),(size_t)\n (MagickPathExtent-(p-format-offset)),p,value);\n /*--------Changed--------*/\n if (written \u003c= 0 || written \u003e (MagickPathExtent - (p - format - offset)))\n return 0;\n offset += (ssize_t)((q - p) - written);\n /*--------Changed--------*/\n *q=c;\n (void) ConcatenateMagickString(filename,q,MagickPathExtent);\n canonical=MagickTrue;\n if (*(q-1) != \u0027%\u0027)\n break;\n p++;\n break;\n }\n case \u0027[\u0027:\n {\n ...\n }\n default:\n break;\n }\n }\n```\n- By updating `offset` based on the difference between template description length `(q - p)` and the number of output bytes `written`, buffer position consistency is maintained.\n- Correction is performed according to the actual template structure, ensuring stable behavior regardless of format length without relying on static constants.\n- Range checking of `written` allows detection of vsnprintf failures and excessive writes.\n\n### Commits\nFixed in https://github.com/ImageMagick/ImageMagick/commit/66dc8f51c11b0ae1f1cdeacd381c3e9a4de69774 and https://github.com/ImageMagick/ImageMagick6/commit/643deeb60803488373cd4799b24d5786af90972e",
"id": "GHSA-qh3h-j545-h8c9",
"modified": "2025-11-03T21:34:07Z",
"published": "2025-08-25T15:43:37Z",
"references": [
{
"type": "WEB",
"url": "https://github.com/ImageMagick/ImageMagick/security/advisories/GHSA-qh3h-j545-h8c9"
},
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2025-53101"
},
{
"type": "WEB",
"url": "https://github.com/ImageMagick/ImageMagick/commit/66dc8f51c11b0ae1f1cdeacd381c3e9a4de69774"
},
{
"type": "WEB",
"url": "https://github.com/ImageMagick/ImageMagick6/commit/643deeb60803488373cd4799b24d5786af90972e"
},
{
"type": "PACKAGE",
"url": "https://github.com/ImageMagick/ImageMagick"
},
{
"type": "WEB",
"url": "https://github.com/dlemstra/Magick.NET/releases/tag/14.7.0"
},
{
"type": "WEB",
"url": "https://lists.debian.org/debian-lts-announce/2025/09/msg00012.html"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:N/I:H/A:H",
"type": "CVSS_V3"
}
],
"summary": "ImageMagick has a Stack Buffer Overflow in image.c"
}
Sightings
| Author | Source | Type | Date |
|---|
Nomenclature
- Seen: The vulnerability was mentioned, discussed, or seen somewhere by the user.
- Confirmed: The vulnerability is confirmed from an analyst perspective.
- Published Proof of Concept: A public proof of concept is available for this vulnerability.
- Exploited: This vulnerability was exploited and seen by the user reporting the sighting.
- Patched: This vulnerability was successfully patched by the user reporting the sighting.
- Not exploited: This vulnerability was not exploited or seen by the user reporting the sighting.
- Not confirmed: The user expresses doubt about the veracity of the vulnerability.
- Not patched: This vulnerability was not successfully patched by the user reporting the sighting.