ESET researchers examined CVE‑2025‑50165, a severe Home windows vulnerability described to grant distant code execution by merely opening a specifically crafted JPG file – one of the extensively used picture codecs. The flaw, discovered and documented by Zscaler ThreatLabz, piqued our curiosity, as Microsoft assessed its severity as essential however deemed its exploitability as much less doubtless. Our root trigger evaluation allowed us to pinpoint the precise location of the defective code and reproduce the crash. We consider that the exploitation state of affairs is more durable than it seems to be.
Key factors of this blogpost:
- ESET researchers provide a deep dive evaluation of the CVE‑2025‑50165 vulnerability, illustrated with pseudocode snippets.
- We offer our methodology to breed the crash utilizing a easy 12-bit or 16-bit JPG picture, and an examination of the preliminary launched patch.
- CVE-2025-50165 is a flaw within the encoding and compressing strategy of a JPG picture, not in its decoding.
- Our conclusion explores and reassesses the exploitability and the assault state of affairs of this flaw.
Overview
On November 20th, 2025, Zscaler ThreatLabz printed an article documenting the invention of CVE‑2025‑50165, a high-impact distant code execution vulnerability current in WindowsCodecs.dll. This library is Home windows’ predominant interface library chargeable for dealing with commonest picture file codecs, corresponding to JPG, PNG, GIF, BMP, and so forth. Zscaler’s findings, in addition to the description supplied by Microsoft, reveal that the flaw stems from the dereference of an uninitialized perform pointer in WindowsCodecs.dll, which is a part of the Home windows Imaging Part. The previous managed to trace down the dereference difficulty contained in the jpeg_finish_compress perform, which occurs to be known as when a JPG picture stream is compressed and (re-)encoded. With regards to image-handling vulnerabilities, one would first consider parsing and decoding bugs that occur as quickly because the picture is rendered. So this fairly particular susceptible code path left us with some questions we needed to reply:
- What are the precise situations to take the susceptible code path resulting in the dereference of the uninitialized perform pointer?
- When is jpeg_finish_compress known as?
- Why is the perform pointer not initialized?
Given how widespread JPG photos are on the net, we needed solutions, so we began by investigating the code that brought on the crash.
Crash website
In line with the CVE‑2025‑50165 entry description, WindowsCodecs.dll variations from 10.0.26100.0 and earlier than 10.0.26100.4946 are affected. We analyzed the susceptible model 10.0.26100.4768 (SHA-1: 5887D96565749067564BABCD3DC5D107AB6666BD), after which carried out a binary comparability with the primary patched model 10.0.26100.4946 (SHA-1: 4EC1DC0431432BC318E78C520387911EC44F84FC). After downloading the corresponding symbols, we appeared on the crashing perform, jpeg_finish_compress. In line with a model string current in WindowsCodecs.dll – libjpeg-turbo model 3.0.2 (construct 20250529) – the DLL depends on a fairly previous implementation of the libjpeg-turbo library (launched on January 24th, 2024) to deal with JPG photos. The publicly out there repository allowed us to map many of the related binary code and constructions to their supply code equivalents. As an example, the compiled model of jpeg_finish_compress is similar to its supply code equal out there right here, as proven in Determine 1.
Based mostly on Zscaler’s findings, the crash occurs at jpeg_finish_compress+0xCC, which corresponds to line 48 in Determine 1, when dereferencing a perform pointer positioned at offset 0x10 of an unknown construction (pub). In line with libjpeg-turbo source code, this corresponds to a perform pointer named compress_data_12. So as to attain this particular path, the data_precision member of jpeg_compress_struct must be set to 12. This corresponds to the bit depth, or in different phrases the variety of bits used to explain colours. Basically, WindowsCodecs.dll crashes when it tries to encode a 12‑bit precision JPG picture.
Patch diffing and root trigger evaluation
Utilizing Diaphora, a binary diffing software, we carried out a diff between the susceptible model 10.0.26100.4768 and the patched model 10.0.26100.4946, as proven in Determine 2.

Surprisingly, the crashing perform jpeg_finish_compress talked about within the article is just not current. Nonetheless, two encoding-related features had been modified: rawtransencode_master_selection and jinit_c_rawtranscode_coef_controller_turbo. The diff between the susceptible and patched variations of rawtransencode_master_selection is proven in Determine 3.

The one related distinction appears to be that the perform jinit_c_rawtranscode_coef_controller_turbo, which was beforehand inlined within the physique of the perform rawtransencode_master_selection, is now separated. Wanting on the patched model of the jinit_c_rawtranscode_coef_controller_turbo perform reveals that the beforehand uninitialized construction member compress_data_12 is now set to level to a perform named rawtranscode_compress_output_16, as proven in Determine 4.

Word that the sector compress_data_16, which was additionally not initialized within the susceptible model, can be set to level to rawtranscode_compress_output_16 within the patched model. This perform is solely a stub perform that calls rawtranscode_compress_output, which can point out that there’s no particular code to deal with both 12-bit or 16-bit precision JPG photos.
Reproducing the crash
As talked about in Zscaler’s article, one can compile the code snippet proposed by Microsoft (https://study.microsoft.com/en-us/home windows/win32/wic/-wic-codec-jpegmetadataencoding#jpeg-re-encode-example-code) to decode and re-encode a JPG picture.
As soon as this program is compiled, the crash might be reproduced by offering both a 12-bit or a 16-bit JPG file. Going via the samples from the libjpeg-turbo repository, a 12-bit precision pattern picture is accessible for obtain at https://github.com/libjpeg-turbo/libjpeg-turbo/blob/predominant/testimages/testorig12.jpg. Feeding this picture to the re-encoding instance software resulted in a crash at the very same location talked about in Zscaler’s article. Determine 5 exhibits the context of the crash throughout a debugging session.

The repeated hex worth 0xBAADF00D pointed to by the reminiscence tackle is a magic worth utilized by the C runtime (CRT) heap when a program calls HeapAlloc to allocate reminiscence. It marks the reminiscence as uninitialized (see https://www.nobugs.org/developer/win32/debug_crt_heap.html).
As indicated beforehand, each analyzed variations of WindowsCodecs.dll seem to have the ability to deal with 16-bit precision JPG photos. However when testing such photos, the re-encoding software crashes when dereferencing the compress_data_16 perform pointer, as noticed in Determine 6.

Having reproduced the crash, we puzzled whether or not this particular vulnerability was additionally current within the supply code of the libjpeg-turbo library.
Exploring the supply code
Going via the commits of libjpeg-turbo revealed that comparable points had been resolved on December 18th, 2024, with commit e0e18de, introducing model 3.1.1. Basically, the commit makes certain that constructions are zero-initialized and that an error is raised if a pointer is NULL. It seems that every one the zero-initializations and checks launched by this commit are absent within the susceptible and patched variations of WindowsCodecs.dll.
The patch message additionally hints at different potential susceptible code paths and, extra importantly, that crashes might also occur within the decompression course of when manipulating a JPG picture, as highlighted by the diff of file jdapistd.c, illustrated in Determine 7.

Because the commit description clearly specifies, a calling software would crash (because of the dereference of an uninitialized perform pointer) solely if it erroneously modifications the data_precision area after calling the jpeg_start_compress or jpeg_start_decompress routines. This creates a fairly particular and certain unrealistic state of affairs the place an software utilizing WindowsCodecs.dll would alter the state of inner constructions. Whereas such functions might exist, it doesn’t seem that the Home windows Imaging Part API permits such conduct.
Exploitability
As revealed by our root trigger evaluation, the core difficulty of CVE‑2025‑50165 resides in WindowsCodecs.dll’s dealing with of JPG photos with an information precision worth apart from the traditional and normal 8-bit. The 2 precision-specific perform pointers (compress_data_12 and compress_data_16) had been uninitialized through the compression course of, creating two susceptible code paths that appear to be reachable solely when (re-)encoding a JPG picture. Merely opening, and due to this fact decoding and rendering, a specifically crafted picture won’t set off the vulnerability. Nonetheless, the susceptible perform jpeg_finish_compress could possibly be known as if the picture is saved or if a bunch software, such because the Microsoft Photographs software, creates thumbnails of photos, as proven in Determine 8.

To ensure that a program to be thought-about susceptible, it wants the next traits:
- makes use of a susceptible model of WindowsCodecs.dll,
- doesn’t crash or abort whereas decoding a 12-bit or 16-bit JPG file, and
- permits the picture to be re-encoded.
Furthermore, as talked about by Zscaler researchers, an tackle leak and sufficient management over the heap are necessary to use this vulnerability.
Conclusion
Though JPG is older, extensively used, and maybe the most well-liked digital picture format in fuzz testing, vulnerabilities can nonetheless be present in some codecs. This examine of CVE‑2025‑50165 additionally highlights the significance of maintaining with safety updates when utilizing third-party libraries.
Root trigger evaluation together with patch diffing proved a really highly effective mixture that allowed us to reply our preliminary questions. We discovered that the bug might be triggered when WindowsCodecs.dll encodes a 12-bit or a 16-bit precision JPG stream as each precision-specific perform pointers had been neither initialized nor checked earlier than being dereferenced. Moreover, we discovered that this course of occurs when such a picture is saved or when a thumbnail is created from it.
This investigation led us to an analogous conclusion as Microsoft’s concerning the exploitability of this vulnerability. Certainly, as WindowsCodecs.dll is a library, a bunch software can be thought-about susceptible if it permits JPG photos to be (re-)encoded, and exploitable provided that an attacker has sufficient management over the appliance (tackle leak, heap manipulation). Placing all of it collectively, it appears certainly that exploitation is unlikely.
Lastly, it’s price mentioning that, as of this writing and based on our exams, newer variations of WindowsCodecs.dll (corresponding to 10.0.22621.6133, SHA-1: 3F3767D05E5A91184005D98427074711F68D9950) implement the completely different modifications talked about in libjpeg-turbo’s commit, successfully addressing the shortage of initialization and performance pointer verification.

