Feb 14, 2026·6 min read·92 visits
Libpng versions 1.6.51 through 1.6.53 contain a heap buffer over-read vulnerability triggered when processing 16-bit interlaced PNGs into 8-bit output. A flaw in how row strides are calculated allows `memcpy` to read out-of-bounds, causing Denial of Service (DoS) or information disclosure.
A regression in the world's most popular image library turns a routine memory copy into a massive heap over-read. By exploiting the 'simplified API' in libpng, attackers can force the library to read beyond allocated bounds using negative or padded row strides, leading to application crashes or potentially leaking heap memory during 16-bit to 8-bit downscaling.
If you've ever opened an image on a computer, you've likely used libpng. It is the reference library for the Portable Network Graphics (PNG) standard, embedded in everything from your web browser to your OS kernel. It is the plumbing of the visual internet. And like all ancient C plumbing, sometimes it leaks.
CVE-2026-22695 is a classic case of "no good deed goes unpunished." It stems from the library's Simplified API—a set of functions designed to save developers from the headache of manual PNG chunk parsing. Specifically, the function png_image_read_direct_scaled acts as a magic black box: you give it a complex PNG (maybe 16-bit, maybe interlaced), and ask for a simple 8-bit buffer back.
The problem? In the quest to handle image scaling and format conversion automatically, the library made a dangerous assumption about memory layout. It trusted the caller's definition of "row stride" (the width of a row in bytes) a little too much, forgetting that the source buffer might be smaller than the destination's stride. This creates a disconnect between where we are reading from and how much we are trying to read.
This vulnerability is a regression, which is developer-speak for "we fixed a bug and created a new one." It was introduced in commit 218612ddd, ironically while trying to fix a different vulnerability (CVE-2025-65018). The developers were trying to optimize how interlaced images are processed when being downscaled from 16-bit to 8-bit color depth.
Here is the logic flaw: When libpng processes an image, it often uses a temporary buffer, let's call it local_row, to hold the data for a single line of the image. The size of this buffer is determined by png_get_rowbytes(), which calculates the actual data width.
However, the output buffer provided by the application might have a different width. This is defined by row_stride. Why would row_stride be different? Two reasons:
The vulnerability occurs because the code used the destination's row_stride to determine how many bytes to copy from the source local_row. If the stride is larger than the actual row width (padding), or if it's negative (which casts to a massive unsigned integer), the memcpy operation goes off the rails.
Let's look at the crime scene in pngread.c. The code essentially performed a memory copy where the size argument was derived from user-controlled input (row_stride) rather than the actual size of the source buffer.
> [!NOTE]
> In C, memcpy(dest, src, size) requires that both dest and src be at least size bytes long. If src is smaller, you are reading uninitialized heap memory.
Here is the vulnerable logic path:
// pngread.c (Vulnerable Logic)
// 1. local_row is allocated based on the ACTUAL image width
png_alloc_size_t row_bytes = png_get_rowbytes(png_ptr, info_ptr);
local_row = png_malloc(png_ptr, row_bytes);
// ... inside the processing loop ...
// 2. The code uses the caller's 'row_stride' to determine copy size
// If row_stride is negative (e.g. -100), casting to size_t makes it HUGE.
memcpy(output_row, local_row, (size_t)row_stride);
// 3. Advance the output pointer
output_row += row_stride;The fix is simple but critical. We must decouple the amount of data we copy from the amount we advance the pointer. We only copy what we have (row_bytes), but we still jump ahead by row_stride to maintain the application's alignment requirements.
// pngread.c (Patched Logic in 1.6.54)
// Only copy the valid data available in local_row
memcpy(output_row, local_row, row_bytes);
// Advance the pointer by the stride (which handles the padding/gap)
output_row += row_stride;To exploit this, we don't need a debugger; we need a weird image and a standard API call. The goal is to trick the application into asking libpng to perform an impossible copy.
The Attack Recipe:
do_local_scale logic path.png_image_read_direct_scaled API (or similar simplified APIs) and request an 8-bit output format.row_stride that is either significantly larger than the image width (excessive padding) OR negative.While an attacker can't always control the arguments passed to the library (the row_stride), many applications calculate this based on metadata or platform standards. For example, an application parsing a PNG to display it on a Windows surface might default to a negative stride for bottom-up rendering.
If the stride is negative, (size_t)row_stride becomes a number close to $2^{64}$. The memcpy tries to read until it hits an unmapped memory page, causing an immediate segmentation fault (DoS). If the stride is just largely padded, it copies adjacent heap chunks into the image output, potentially leaking sensitive data.
So, is this the end of the world? Probably not. Is it bad? Yes.
Denial of Service (DoS) is the guaranteed impact. By feeding a malicious image to a server processing user uploads (e.g., a profile picture resizer), an attacker could crash the worker process. If the process doesn't restart automatically, or if the attacker floods the service, the application goes down.
Information Disclosure is the more insidious risk. Since this is an over-read, libpng is copying data from the heap into the pixel buffer. That means whatever was sitting next to local_row in memory—previous HTTP requests, encryption keys, other users' images—gets baked into the resulting image.
If the attacker can download the processed image (which they usually can, seeing as they uploaded it), they can render the pixels and reconstruct the leaked memory. It's like Heartbleed, but for pixels.
The remediation is straightforward: Update libpng to version 1.6.54.
If you are a developer using libpng directly, verify that you are not statically linking an older version. Check your dependencies. If you are a Linux sysadmin, apt update or yum update should be your priority today.
For those who cannot patch immediately, you might be able to mitigate this by ensuring your application:
png_image_read...).Ultimately, patch the library. It's the only way to be sure.
CVSS:3.1/AV:L/AC:L/PR:N/UI:R/S:U/C:L/I:N/A:H| Product | Affected Versions | Fixed Version |
|---|---|---|
libpng PNG Group | >= 1.6.51, <= 1.6.53 | 1.6.54 |
| Attribute | Detail |
|---|---|
| CWE ID | CWE-125 (Heap Buffer Over-read) |
| CVSS v3.1 | 6.1 (Medium) |
| Attack Vector | Local (File Processing) |
| Availability Impact | High (Crash) |
| Confidentiality Impact | Low (Heap Leak) |
| Exploit Status | PoC Available |
The software reads data past the end, or before the beginning, of the intended buffer.
A critical stored Cross-Site Scripting (XSS) vulnerability was identified in Froxlor server administration software panel before version 2.3.8. Authenticated customers with DNS editor privileges can inject malicious JavaScript into DNS TXT records. Because the application processes these values via a raw formatting callback without context-aware HTML entity encoding, the payload executes in the security context of administrative users who view the affected domain's DNS zones.
An authenticated administrator with privileges to manage admin accounts (such as change_serversettings) can execute arbitrary SQL commands via a second-order SQL injection vulnerability. The flaw resides in Froxlor's administrative API endpoints, specifically during the handling of IP address mapping parameters which are stored as serialized arrays and later interpolated without sanitization into active database queries. This vulnerability allows high-privileged administrative attackers to compromise the database. By injecting a payload into administrative profile metadata, an attacker can extract sensitive credentials, manipulate backend settings, or potentially disrupt database integrity. The vulnerability affects all versions of Froxlor prior to 2.3.8.
CVE-2026-54543 is a DNS Resource Record (RR) Injection vulnerability in Froxlor, an open-source server administration control panel. Prior to version 2.3.8, the DomainZones.add API command failed to perform strict sanitization and validation on the user-controlled record (label) and type parameters before serializing them into BIND-compatible zone files. An authenticated customer with DNS zone management permissions can inject control characters, breaking out of the original record context to define unauthorized resource records within managed zones.
CVE-2026-42533 is a critical security vulnerability discovered in NGINX Open Source, NGINX Plus, NGINX Ingress Controller, and related products, referred to as the 'Two-Pass Capture-Clobbering' bug. The flaw is situated within NGINX's internal evaluation engine when handling complex variables, exposing a heap-based buffer overflow and information leak when a configuration chains regular expression-based map directives with numbered capture groups. An unauthenticated remote attacker can exploit this weakness by transmitting crafted HTTP requests to trigger remote code execution or defeat ASLR.
Froxlor prior to version 2.3.8 contains a high-severity architectural flaw where the standalone lib/ajax.php entry point bypasses the centralized request validation in lib/init.php. Unauthenticated remote attackers can leverage Cross-Site Request Forgery (CSRF) to induce authenticated administrators to submit forged requests that modify API key whitelists and expiration dates, potentially yielding persistent, out-of-band administrative control.
An insecure data retrieval flaw in the Froxlor server administration panel API allows authenticated remote attackers to retrieve unredacted bcrypt password hashes and Base32-encoded Time-Based One-Time Password (TOTP) seeds. Affected endpoints include several 'get' and 'listing' handlers for customers, administrators, and FTP accounts. Utilizing these leaked parameters, attackers can crack the password hashes offline and concurrently generate valid second-factor authentication codes to completely bypass access controls.