VYPR
High severity8.8NVD Advisory· Published May 27, 2026

CVE-2026-44988

CVE-2026-44988

Description

LibVNCClient is a library for easy implementation of a VNC client. In 0.9.15 and earlier, LibVNCClient's Tight encoding decoder uses fixed-size 2048-pixel scratch buffers for the Gradient filter, but it does not reject Tight rectangles whose width is larger than 2048 pixels. A malicious VNC server can send a crafted FramebufferUpdate rectangle using Tight encoding with NoZlib | ExplicitFilter and the Gradient filter. When a LibVNCClient-based client connects, the client processes the server-controlled rectangle width and writes beyond fixed-size Gradient buffers. This vulnerability is fixed with commit 5b270544b85233668b98161323297d418a8f5fd1.

AI Insight

LLM-synthesized narrative grounded in this CVE's description and references.

LibVNCClient 0.9.15 and earlier allows heap/stack OOB writes via crafted Tight Gradient rectangles.

Vulnerability

In LibVNCClient version 0.9.15 and earlier, the Tight encoding decoder uses fixed-size 2048-pixel scratch buffers for the Gradient filter, defined in include/rfb/rfbclient.h as TIGHT_GRADIENT_MAX_WIDTH. The code does not reject Tight rectangles whose width exceeds 2048 pixels. When a malicious VNC server sends a crafted FramebufferUpdate rectangle using Tight encoding with NoZlib | ExplicitFilter and the Gradient filter, the client processes the server-controlled rectangle width and writes beyond the fixed-size Gradient buffers (thisRow stack array and client->tightPrevRow heap buffer), triggering out-of-bounds writes [1][2].

Exploitation

An attacker operating a malicious or compromised VNC server can send a specially crafted FramebufferUpdate rectangle that uses Tight encoding with the Gradient filter and a rectangle width larger than 2048 pixels. No authentication or prior user interaction beyond the client connecting to the server is required. The exploit sequence is: the VNC server sends the oversized rectangle, the LibVNCClient processes it in HandleTightBPP, calls FilterGradientBPP or FilterGradient24, and writes pixel data beyond the bounds of the stack buffer thisRow and the heap buffer tightPrevRow [1].

Impact

Successful exploitation results in client-side memory corruption. The out-of-bounds write can overwrite the rfbClient structure's data pointers and function pointers, enabling constrained local read/write primitives. This can potentially lead to arbitrary code execution (RCE) with the privileges of the client application, though a reliable full RCE exploit was not claimed in the reported advisory [1].

Mitigation

The vulnerability is fixed in commit 5b270544b85233668b98161323297d418a8f5fd1 [2]. This commit adds a bounds check in HandleTightBPP that rejects rectangles with width exceeding TIGHT_GRADIENT_MAX_WIDTH, and adjusts the thisRow buffer size to use TIGHT_GRADIENT_MAX_WIDTH*3 instead of the hardcoded 2048*3. Users should upgrade to a version containing this commit, or apply the patch manually. No workarounds are documented, and the issue is not listed on CISA's KEV.

AI Insight generated on May 27, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.

Affected products

2

Patches

1
5b270544b852

libvncclient: fix Tight gradient decoding overflow

https://github.com/LibVNC/libvncserverKang Hee chanMay 6, 2026via text-mined
2 files changed · +9 4
  • include/rfb/rfbclient.h+2 1 modified
    @@ -328,10 +328,11 @@ typedef struct _rfbClient {
     	rfbBool zlibStreamActive[4];
     
     	/* Filter stuff. Should be initialized by filter initialization code. */
    +#define TIGHT_GRADIENT_MAX_WIDTH 2048
     	rfbBool cutZeros;
     	int rectWidth, rectColors;
     	char tightPalette[256*4];
    -	uint8_t tightPrevRow[2048*3*sizeof(uint16_t)];
    +	uint8_t tightPrevRow[TIGHT_GRADIENT_MAX_WIDTH*3*sizeof(uint16_t)];
     
     #ifdef LIBVNCSERVER_HAVE_LIBJPEG
     	/** JPEG decoder state (obsolete-- do not use). */
    
  • src/libvncclient/tight.c+7 3 modified
    @@ -229,6 +229,11 @@ HandleTightBPP (rfbClient* client, int rx, int ry, int rw, int rh)
           bitsPixel = InitFilterPaletteBPP(client, rw, rh);
           break;
         case rfbTightFilterGradient:
    +      if (rw > TIGHT_GRADIENT_MAX_WIDTH) {
    +	rfbClientLog("Tight Gradient rectangle width %d exceeds maximum %d.\n",
    +		     rw, TIGHT_GRADIENT_MAX_WIDTH);
    +	return FALSE;
    +      }
           filterFn = FilterGradientBPP;
           bitsPixel = InitFilterGradientBPP(client, rw, rh);
           break;
    @@ -430,7 +435,7 @@ FilterGradient24 (rfbClient* client, int srcx, int srcy, int numRows)
       CARDBPP *dst =
         (CARDBPP *)&client->frameBuffer[(srcy * client->width + srcx) * BPP / 8];
       int x, y, c;
    -  uint8_t thisRow[2048*3];
    +  uint8_t thisRow[TIGHT_GRADIENT_MAX_WIDTH*3];
       uint8_t pix[3];
       int est[3];
     
    @@ -473,7 +478,7 @@ FilterGradientBPP (rfbClient* client, int srcx, int srcy, int numRows)
       int x, y, c;
       CARDBPP *src = (CARDBPP *)client->buffer;
       uint16_t *thatRow = (uint16_t *)client->tightPrevRow;
    -  uint16_t thisRow[2048*3];
    +  uint16_t thisRow[TIGHT_GRADIENT_MAX_WIDTH*3];
       uint16_t pix[3];
       uint16_t max[3];
       int shift[3];
    @@ -705,4 +710,3 @@ ReadCompactLen (rfbClient* client)
     /* LIBVNCSERVER_HAVE_LIBZ and LIBVNCSERVER_HAVE_LIBJPEG */
     #endif
     #endif
    -
    

Vulnerability mechanics

Root cause

"Missing bounds check on rectangle width in Tight Gradient decoder allows writes beyond fixed-size 2048-pixel scratch buffers."

Attack vector

A malicious VNC server sends a crafted FramebufferUpdate rectangle using Tight encoding with NoZlib | ExplicitFilter and the Gradient filter, specifying a width larger than 2048 pixels [ref_id=1]. When a LibVNCClient-based client connects and processes the server-controlled rectangle width, the decoder writes beyond the fixed-size `tightPrevRow` and `thisRow` buffers [ref_id=1]. This triggers heap-buffer-overflow (via `memset` in `InitFilterGradientBPP`) and stack-buffer-overflow (via `thisRow` writes in `FilterGradient24`/`FilterGradientBPP`) [ref_id=1]. The attacker must operate a VNC server that the victim client connects to; no authentication is required [ref_id=1].

Affected code

The vulnerable code is in `src/libvncclient/tight.c` and `include/rfb/rfbclient.h` [patch_id=2691372]. The fixed-size buffers are `client->tightPrevRow` (declared as `uint8_t tightPrevRow[2048*3*sizeof(uint16_t)]` in `rfbclient.h:334`) and the stack-local arrays `uint8_t thisRow[2048*3]` in `FilterGradient24` and `uint16_t thisRow[2048*3]` in `FilterGradientBPP` [ref_id=1]. The `HandleTightBPP` function at `tight.c:231-233` selects the Gradient filter without checking `rw` against the 2048-pixel limit [ref_id=1].

What the fix does

The patch adds a width check in `HandleTightBPP` that rejects Tight Gradient rectangles wider than `TIGHT_GRADIENT_MAX_WIDTH` (2048) before calling `InitFilterGradientBPP` or `FilterGradientBPP` [patch_id=2691372]. It also replaces the hardcoded `2048*3` array dimensions with `TIGHT_GRADIENT_MAX_WIDTH*3` in both `FilterGradient24` and `FilterGradientBPP`, and defines the macro in `rfbclient.h` alongside `tightPrevRow` [patch_id=2691372]. This closes the vulnerability by ensuring the buffer sizes and the runtime width check use the same constant, so no oversized rectangle can reach the gradient filter functions [patch_id=2691372].

Preconditions

  • networkVictim must connect to a malicious or compromised VNC server.
  • authNo authentication required; the bug is triggered during normal FramebufferUpdate processing.
  • inputServer sends a Tight-encoded rectangle with NoZlib | ExplicitFilter, Gradient filter, and width > 2048 pixels.

Generated on May 27, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.

References

2

News mentions

0

No linked articles in our index yet.