This is a bad lock on an interior door, not a busted front gate
CVE-2026-50259 is a stack-based buffer overflow in the XKB SetMap request path of the X.Org X server and Xwayland. In _XkbSetMapChecks(), a fixed stack buffer mapWidths[256] is indexed using client-controlled key-type data via CheckKeyTypes(), so a connected X11 client can write past the end of the stack buffer. Upstream fixed it in xorg-server 21.1.23 and xwayland 24.1.12; Debian tracks older packaged branches as vulnerable until backported fixes land, and Ubuntu had the issue under evaluation when reviewed.
The vendor's 7.8/HIGH score is technically defensible in a lab because memory corruption plus potential privilege escalation is real. In enterprise reality, it overstates urgency: the attacker must already have local foothold or X11 client access to the victim display/session, and the best-case impact often collapses further on modern rootless Xwayland and rootless Xorg deployments where the easy 'become root via X server' path is gone.
4 steps from start to impact.
Get onto the host or into the user's X trust boundary
libxcb or python-xlib client is enough to speak the required protocol.- Attacker already has local code execution, user shell access, or permitted X11 client connectivity
- Target is running vulnerable
XorgorXwayland
- Most enterprises do not expose X11 directly to the internet
- Wayland-first desktops shrink the reachable population for classic Xorg attack paths
- Xauthority, local sockets, container isolation, and SSH forwarding rules often limit who can connect
Send a malicious XKB SetMap request
libxcb/libX11, the attacker sends a crafted XKB SetMap request that causes CheckKeyTypes() to index mapWidths[256] out of bounds. This is low-complexity once the attacker can talk to the server because the advisory points directly at the vulnerable code path and the fixing commit narrows the bug shape.- XKB extension reachable in the target server
- Attacker can submit arbitrary X11 protocol messages
- No widely circulated public weaponized PoC was found during review
- Reliability may vary across builds, mitigations, and server modes
Corrupt stack memory in the X server process
- Target binary lacks effective hardening against turning the overflow into code execution
- The crafted request lands on the vulnerable path consistently
- Stack canaries, ASLR, PIE, and distro hardening reduce exploit reliability
- A crash is easier than a stable privilege-escalation chain
journalctl, ABRT/apport, and EDR memory-corruption telemetry can catch failed attempts.Try to turn process compromise into privilege gain
- X server runs with privileges worth stealing, or the session context is itself high value
- Exploit succeeds beyond mere denial of service
- Modern Xwayland is typically not running as root
- Even successful code execution may stay trapped in the current user/session context
Xorg/Xwayland, and EDR lineage alerts are the best signals.X11Forwarding exposure, and remove permissive xhost usage where it still exists. This cuts the reachable population immediately; for a MEDIUM verdict there is no mitigation SLA, so use this as risk reduction while you work inside the remediation window.Xorg or Xwayland crashes, unexpected child processes, and unusual command execution spawned from those parents. This is especially useful on shared Linux desktops and VDI where a post-entry local exploit is more realistic than on locked-down servers.- Perimeter WAFs or internet IDS signatures: they do nothing for a local/X11-session attack path.
- MFA: useful for initial access, irrelevant once a process can already talk to the local X server.
- Relying on 'Wayland is enabled' alone: many apps still traverse Xwayland, so the vulnerable code may still be present and reachable.
The supporting signals.
| In-the-wild status | No evidence of active exploitation found in public sources reviewed; Red Hat/CISA ADP marks SSVC Exploitation: none. |
|---|---|
| PoC availability | No public weaponized GitHub PoC was located during review. What *is* public is the advisory, the vulnerable function, and the fix commit, which lowers reverse-engineering effort. |
| EPSS | 0.00012 from the supplied intel. That is effectively background-noise probability, but I did not independently verify the exact percentile from a FIRST snapshot. |
| KEV status | Not listed in the CISA KEV catalog at time of review. |
| CVSS vector reality check | CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H accurately says *local, low-priv, no user interaction*; that also means this is post-entry, not a front-door exploit. |
| Affected versions | Upstream advisory says X.Org X server prior to 21.1.23 and Xwayland prior to 24.1.12. |
| Fixed versions | Upstream fixed in xorg-server 21.1.23 and xwayland 24.1.12. Debian shows fixes in unstable as xorg-server 2:21.1.23-1 and xwayland 2:24.1.12-1; bookworm/trixie entries were still marked vulnerable when reviewed. Ubuntu listed xorg-server/xwayland as *Needs evaluation* on June 6, 2026. |
| Exposure / scanning data | No CVE-specific GreyNoise/Censys/Shodan telemetry was found. That's expected: this bug is generally not internet-scannable in the usual sense because the attacker needs X11 client reachability into a live desktop/session trust boundary. |
| Disclosure timeline | Public advisory landed 2026-06-02; the CVE record was published 2026-06-05. If your internal feeds key off CVE publish date only, you were already three days late to the party. |
| Reporter | Reported by Anonymous working with Trend Micro Zero Day Initiative, tracked as ZDI-CAN-30161. |
Sources.
Why this verdict
- Requires X11 client reachability:
AV:L/PR:Lhere really means the attacker is already on the box, in the session, or otherwise allowed to talk to the X server. That's compounding downward pressure because it assumes a prior compromise stage or a trusted local-user position. - Modern deployments blunt the blast radius: on rootless Xwayland and many rootless Xorg setups, a successful exploit does not automatically become root. Same-user compromise or session DoS is still bad, but it's not the same as host-level takeover.
- No heat around exploitation: no KEV listing, no public exploitation evidence found, no public weaponized PoC found, and a tiny supplied EPSS all argue against treating this like an urgent broad spray-and-pray threat.
Why not higher?
Because this is not an unauthenticated remote bug and not meaningfully internet-reachable in normal enterprise layouts. You have to already be inside the machine or inside the user's X trust boundary, which means the vulnerability rides *after* initial access rather than creating it.
Why not lower?
Because it is still real memory corruption in a ubiquitous desktop component, and exploitation can plausibly yield more than a crash on the wrong build or legacy rootful Xorg deployment. If you run Linux VDI, engineering workstations, kiosks, or long-lived X11-forwarding environments, the affected population is non-trivial enough that this should not be shrugged off as hygiene-only.
Crowdsourced verification payload.
Run this on the target Linux host as the logged-in user or with sudo; root is not strictly required, but package-manager queries are more reliable with normal local access. Save as check-cve-2026-50259.sh and run bash check-cve-2026-50259.sh or bash check-cve-2026-50259.sh /usr/bin/Xorg /usr/bin/Xwayland; it checks installed binaries and package metadata, then prints VULNERABLE, PATCHED, or UNKNOWN.
#!/usr/bin/env bash
# check-cve-2026-50259.sh
# Detect likely exposure to CVE-2026-50259 on Linux hosts.
# Output: VULNERABLE / PATCHED / UNKNOWN
# Exit codes: 0=PATCHED, 1=VULNERABLE, 2=UNKNOWN
set -u
FIXED_XORG_UPSTREAM="21.1.23"
FIXED_XWAYLAND_UPSTREAM="24.1.12"
STATUS="PATCHED"
DETAILS=()
ver_ge() {
# returns 0 if $1 >= $2
[ "$(printf '%s\n%s\n' "$1" "$2" | sort -V | tail -n1)" = "$1" ]
}
extract_ver() {
# pull first dotted version from input
echo "$1" | grep -Eo '[0-9]+(\.[0-9]+){1,3}' | head -n1
}
check_bin() {
local name="$1"
local path="$2"
local fixed="$3"
local v out
if [ ! -x "$path" ]; then
DETAILS+=("$name: not present")
return 0
fi
out="$($path -version 2>/dev/null || $path --version 2>/dev/null || true)"
v="$(extract_ver "$out")"
if [ -z "$v" ]; then
DETAILS+=("$name: version unknown from binary output")
STATUS="UNKNOWN"
return 0
fi
if ver_ge "$v" "$fixed"; then
DETAILS+=("$name: binary version $v >= fixed upstream $fixed")
else
DETAILS+=("$name: binary version $v < fixed upstream $fixed")
if [ "$STATUS" != "UNKNOWN" ]; then STATUS="VULNERABLE"; fi
fi
}
check_dpkg() {
command -v dpkg-query >/dev/null 2>&1 || return 0
local pkg ver
for pkg in xserver-xorg-core xwayland; do
if dpkg-query -W -f='${Version}' "$pkg" >/dev/null 2>&1; then
ver="$(dpkg-query -W -f='${Version}' "$pkg" 2>/dev/null)"
DETAILS+=("dpkg:$pkg=$ver")
# Known Debian unstable fixed package versions from tracker.
if [ "$pkg" = "xserver-xorg-core" ]; then
if dpkg --compare-versions "$ver" ge "2:21.1.23-1"; then
DETAILS+=("dpkg:$pkg meets Debian unstable fixed threshold")
else
DETAILS+=("dpkg:$pkg below Debian unstable fixed threshold; could still be backported later on vendor branches")
[ "$STATUS" = "PATCHED" ] && STATUS="UNKNOWN"
fi
fi
if [ "$pkg" = "xwayland" ]; then
if dpkg --compare-versions "$ver" ge "2:24.1.12-1"; then
DETAILS+=("dpkg:$pkg meets Debian unstable fixed threshold")
else
DETAILS+=("dpkg:$pkg below Debian unstable fixed threshold; could still be backported later on vendor branches")
[ "$STATUS" = "PATCHED" ] && STATUS="UNKNOWN"
fi
fi
fi
done
}
check_rpm() {
command -v rpm >/dev/null 2>&1 || return 0
local pkg
for pkg in xorg-x11-server-Xorg xorg-x11-server-Xwayland; do
if rpm -q "$pkg" >/dev/null 2>&1; then
DETAILS+=("rpm:$pkg=$(rpm -q "$pkg" 2>/dev/null)")
DETAILS+=("rpm:$pkg installed; vendor backport status must be validated against distro advisory")
[ "$STATUS" = "PATCHED" ] && STATUS="UNKNOWN"
fi
done
}
XORG_PATH="${1:-$(command -v Xorg 2>/dev/null || echo /usr/bin/Xorg)}"
XWAYLAND_PATH="${2:-$(command -v Xwayland 2>/dev/null || echo /usr/bin/Xwayland)}"
check_bin "Xorg" "$XORG_PATH" "$FIXED_XORG_UPSTREAM"
check_bin "Xwayland" "$XWAYLAND_PATH" "$FIXED_XWAYLAND_UPSTREAM"
check_dpkg
check_rpm
# If neither binary exists and no packages were detected, result is PATCHED/NOT APPLICABLE.
# We keep PATCHED to satisfy the required output vocabulary.
echo "$STATUS"
printf '%s
' "${DETAILS[@]}"
case "$STATUS" in
PATCHED) exit 0 ;;
VULNERABLE) exit 1 ;;
*) exit 2 ;;
esac