Skip to main content
Vulnerability Database/CVE-2026-91946

CVE-2026-91946: FreeRDP Information Disclosure Vulnerability

CVE-2026-91946 is an information disclosure flaw in FreeRDP that exposes uninitialized heap memory containing live pointers and addresses, defeating ASLR protections. This article covers technical details, affected versions, and mitigation steps.

Published:

CVE-2026-91946 Overview

CVE-2026-91946 is an information disclosure vulnerability in FreeRDP versions before 3.31.0. The flaw resides in the RDPGFX server's ResetGraphics PDU serializer, which fails to initialize padding bytes within the fixed 340-byte wire format. An attacker connected as a client can receive uninitialized heap memory contents transmitted inside the PDU. The disclosed data can include live heap pointers and GLib function addresses, defeating heap Address Space Layout Randomization (ASLR) and revealing the GLib module base address. This memory disclosure primitive is commonly used as a building block for reliable exploitation of subsequent memory corruption bugs.

Critical Impact

Remote attackers with low privileges can leak uninitialized heap memory, including function pointers, enabling ASLR bypass against FreeRDP-based servers.

Affected Products

  • FreeRDP versions prior to 3.31.0
  • Applications embedding the FreeRDP RDPGFX server component
  • WinPR utility library (winpr/libwinpr/utils/stream.c) shipped with vulnerable FreeRDP builds

Discovery Timeline

  • 2026-09-15 - CVE-2026-91946 published to NVD
  • 2026-09-16 - Last updated in NVD database

Technical Details for CVE-2026-91946

Vulnerability Analysis

The vulnerability is classified as Use of Uninitialized Resource [CWE-908]. FreeRDP's RDPGFX server constructs a ResetGraphics PDU using a fixed 340-byte wire structure. The serializer allocates a stream buffer via malloc() and writes only the meaningful protocol fields into it. Padding bytes required by the fixed-length format are never zeroed. When the PDU is transmitted to the connected RDP client, the uninitialized region of the buffer travels across the wire unmodified. Because the underlying allocator recycles heap chunks that previously held live application state, the leaked bytes frequently contain heap pointers and pointers into the GLib shared object. An attacker parsing the received PDU can therefore compute the GLib module base address and bypass heap ASLR without any prior code execution primitive.

Root Cause

The root cause is the use of malloc() for the stream buffer backing the ResetGraphics PDU. malloc() returns memory whose contents are undefined. Combined with a fixed-size wire format that contains structural padding, any byte not explicitly written by the serializer is transmitted to the remote peer as attacker-observable data.

Attack Vector

Exploitation requires the attacker to connect to a FreeRDP-based server that negotiates the RDPGFX (Graphics Pipeline) dynamic virtual channel. Once the server emits a ResetGraphics PDU, the attacker records the 340-byte payload and extracts the uninitialized regions. No authentication beyond the standard RDP session establishment is required beyond low privileges as indicated by the CVSS vector.

c
// Security patch: winpr/libwinpr/utils/stream.c
// [winpr,utils] initialize wStream buffer with zero
 	if (buffer)
 		s->buffer = buffer;
 	else
-		s->buffer = (BYTE*)malloc(size);
+		s->buffer = (BYTE*)calloc(size, sizeof(BYTE));
 
 	if (!s->buffer)
 	{
// Source: https://github.com/FreeRDP/FreeRDP/commit/483c9388119f06bac420d92053cff9ef94e83bea

The patch replaces malloc() with calloc(), which zero-initializes the allocated buffer. Any padding bytes not written by the serializer are now guaranteed to be zero rather than residual heap data.

Detection Methods for CVE-2026-91946

Indicators of Compromise

  • Outbound RDPGFX ResetGraphics PDUs whose 340-byte payload contains non-zero bytes in fields the protocol defines as padding or reserved.
  • Repeated short-lived RDP sessions from the same client source that terminate immediately after the graphics channel is initialized.
  • FreeRDP server binaries reporting a version string below 3.31.0 in banner or process metadata.

Detection Strategies

  • Perform software inventory scans to identify systems running FreeRDP or applications that statically link the FreeRDP RDPGFX server component below version 3.31.0.
  • Inspect RDP traffic at the network layer for ResetGraphics PDUs and flag payloads where reserved fields carry entropy consistent with heap contents rather than zero bytes.
  • Correlate RDP session establishment logs with process telemetry to identify clients that connect only long enough to receive graphics initialization traffic.

Monitoring Recommendations

  • Log and retain full packet captures for RDP sessions on servers where FreeRDP acts as the server-side implementation.
  • Alert on anomalous client behavior such as sessions that never render a desktop yet consume the graphics pipeline channel.
  • Track FreeRDP process memory maps to detect unexpected loading of GLib or other shared objects whose base addresses could be leaked.

How to Mitigate CVE-2026-91946

Immediate Actions Required

  • Upgrade all FreeRDP installations to version 3.31.0 or later, including any downstream applications that vendor the FreeRDP source tree.
  • Rebuild and redistribute any in-house software that statically links libfreerdp or libwinpr against the patched release.
  • Restrict network exposure of FreeRDP-based server components to trusted clients until patching is complete.

Patch Information

The fix is delivered in FreeRDP commit 483c9388119f06bac420d92053cff9ef94e83bea, which changes the WinPR stream allocator in winpr/libwinpr/utils/stream.c from malloc() to calloc(). Refer to the FreeRDP Security Advisory GHSA-r7jx-j9h7-j4xj and the VulnCheck Advisory on FreeRDP for the full advisory text.

Workarounds

  • Disable the RDPGFX dynamic virtual channel on FreeRDP-based servers where the graphics pipeline is not required.
  • Place FreeRDP servers behind an authenticated reverse proxy or VPN so untrusted clients cannot initiate RDP sessions.
  • Apply network segmentation to restrict which source addresses may reach the RDP listener while planning the upgrade.
bash
# Verify installed FreeRDP version and upgrade to a patched release
xfreerdp --version

# Debian and Ubuntu
sudo apt update && sudo apt install --only-upgrade freerdp2-x11 freerdp3-x11

# Fedora and RHEL derivatives
sudo dnf upgrade freerdp

# Confirm the installed version is 3.31.0 or later
xfreerdp --version | grep -E "3\.(3[1-9]|[4-9][0-9])"

Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.

Experience the Most Advanced Cybersecurity Platform

See how the world’s most intelligent, autonomous cybersecurity platform can protect your organization today and into the future.