A booby-trapped welcome mat that only hurts you if you walk up to the wrong front door
CVE-2026-55200 is an integer-overflow-to-heap-overflow in libssh2's ssh2_transport_read() function, present in every version through 1.11.1. During SSH packet parsing, the function reads the attacker-controlled packet_length field but only rejects values below 1 — it never enforces an upper bound. A value of 0xFFFFFFFF wraps to a tiny allocation via 32-bit arithmetic, while subsequent code writes the full oversized payload into that undersized buffer. The result is a controlled heap write that can reach code execution. Because libssh2 is linked into curl, Git (Windows), PHP's ssh2 extension, backup agents, and firmware updaters, the vulnerable surface is enormous — but only on the *client side*. A malicious or compromised SSH *server* (or a man-in-the-middle) sends the crafted packet; a vulnerable client that connects to it is the victim.
The vendor (VulnCheck as CNA) scored this 9.2 CRITICAL under CVSS 4.0 and 8.1 HIGH under CVSS 3.1. Red Hat independently rescored to 7.1 by adding UI:R and lowering availability impact, reasoning that the victim must actively initiate a connection to the attacker's endpoint. Red Hat's adjustment is closer to reality. The 9.2 CRITICAL label from VulnCheck overstates the operational risk: this is not a scan-and-exploit server-side flaw. An attacker needs to control what server the victim connects to — via DNS poisoning, MITM, compromising a legitimate SSH host, or tricking an automated pipeline into cloning a malicious repo. SSH host-key verification (known_hosts) blocks many MITM scenarios outright. The vendor score is defensible for worst-case analysis but misleads defenders into treating this like a wormable server bug, which it is not.
4 steps from start to impact.
Establish malicious SSH endpoint
exploitarium repo (bikini/exploitarium) implements a minimal SSH server that completes the version exchange and then sends the crafted packet.- Network position to intercept or redirect SSH traffic, OR control of a server the victim will connect to
- Knowledge of the target's SSH connection targets
- SSH host-key checking (
known_hosts,StrictHostKeyChecking=yes) blocks MITM for previously-seen hosts - Enterprise DNS infrastructure is typically well-controlled; internal DNS poisoning requires prior access
- Compromising a trusted SSH host is itself a significant prerequisite that implies prior access
packet_length values in the binary packet protocol.Victim connects to malicious endpoint
ssh2_connect(), a backup agent, or a CI/CD runner — initiates an SSH session to the attacker-controlled endpoint. The connection can be automated (cron job, pipeline step, scheduled backup) or user-initiated. No authentication or special configuration is required from the victim side.- Victim system runs an application linked against libssh2 ≤ 1.11.1
- The application connects to the attacker-controlled or MITM'd SSH endpoint
- Many Linux Git and SSH operations use OpenSSH's libssh, not libssh2 — check your build
- Automated processes typically connect to a static, known set of endpoints
- Outbound SSH to arbitrary external hosts is often blocked by enterprise firewalls
ldd audits for libssh2 linkage.Crafted packet triggers integer overflow
packet_length set to 0xFFFFFFFF. In ssh2_transport_read(), this value is added to small constants using 32-bit arithmetic, wrapping around to a tiny number (e.g., 4–8 bytes). libssh2 calls realloc() or malloc() with the tiny result. The function then proceeds to read the full ~4 GB of declared payload into the undersized buffer.- Vulnerable libssh2 ≤ 1.11.1 processes the incoming packet
- No application-layer packet-size validation overrides the library behavior
- None once the connection reaches this point — the overflow is deterministic
Heap corruption and code execution
exploitarium PoC demonstrates controlled local RCE using this primitive. The attacker gains code execution in the context of the calling process — which could be curl, git, a PHP worker, or a backup daemon.- Heap layout must be predictable enough for reliable exploitation
- Target binary must not have full CFI or shadow-stack protections
- ASLR raises the bar for reliable exploitation on 64-bit systems
- Modern glibc heap hardening (safe-linking in tcache/fastbins since glibc 2.32) complicates but does not prevent exploitation
- Some applications fork-per-connection, which can leak ASLR bases via crash oracles
StrictHostKeyChecking=yes and populated known_hosts files on all systems that use libssh2-linked tools (curl, Git, PHP, backup agents). This blocks MITM-based exploitation by rejecting connections to servers with unknown or changed host keys. Audit CI/CD pipelines and scripts for StrictHostKeyChecking=no or -o StrictHostKeyChecking=accept-new and remove them. Deploy within 30 days per noisgate mitigation SLA for HIGH.apt-get update && apt-get upgrade libssh2-1 or zypper update libssh2-1 or the equivalent for your distro. For systems building libssh2 from source, cherry-pick commit 97acf3df. Target remediation within 180 days per noisgate remediation SLA for HIGH, but prioritize CI/CD and backup hosts within 30 days.ldd $(which curl) | grep libssh and similar checks to determine which binaries actually link libssh2. Prioritize patching only the systems that are actually vulnerable. This reduces your remediation scope and may show your exposure is smaller than feared.- WAF / reverse proxy in front of SSH — This vulnerability is in the SSH binary packet protocol, not HTTP. Web application firewalls do not inspect SSH traffic and provide zero protection.
- Updating OpenSSH — OpenSSH and libssh2 are completely separate projects. Patching OpenSSH to the latest version does not fix libssh2. They share no code.
- Disabling SSH server on vulnerable hosts — The vulnerability is client-side. Disabling the SSH *daemon* (
sshd) does not help; the risk comes from outbound SSH *client* connections made by applications linked against libssh2. - Network-level SSH traffic inspection — While theoretically possible to detect oversized
packet_lengthfields, SSH traffic is encrypted after key exchange. The malicious packet is sent during the handshake (before encryption in some cases), but most network security tools do not parse SSH binary packet protocol headers at this depth.
The supporting signals.
| In-the-Wild Status | No confirmed exploitation. Not listed in CISA KEV. No GreyNoise tags or Shadowserver observations as of 2026-10-02. The client-side attack vector makes mass scanning impractical — attackers cannot simply probe ports. |
|---|---|
| Proof-of-Concept | Public. Three GitHub repos: bikini/exploitarium (original, includes local RCE harness), 0xBlackash/CVE-2026-55200, xd20111/CVE-2026-55200. The exploitarium PoC is a malicious SSH server scaffold — not a turnkey remote exploit but demonstrates the heap write primitive reliably. |
| EPSS | 0.00825 (≈ top 18%). Low probability of exploitation in the next 30 days, consistent with the client-side attack vector and absence of in-the-wild activity. EPSS models penalize vulns that require victim-initiated connections. |
| KEV Status | Not listed as of 2026-10-02. No known deadline from CISA BOD 22-01. |
| CVSS Vector | Vendor (CNA): CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:H = 8.1. VulnCheck CVSS 4.0: 9.2. Red Hat rescored: CVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:U/C:H/I:H/A:L = 7.1. The AC:H reflects the MITM/malicious-server prerequisite; Red Hat's UI:R addition is arguably more accurate for interactive use cases. |
| Affected Versions | All libssh2 versions ≤ 1.11.1. Effectively every released version — the upper-bound check was never present. Debian bullseye's older libssh2 (1.9.0) is reportedly not affected per Debian tracker (vulnerable code path absent). |
| Fixed Versions | No official libssh2 release. Fix is in commit 97acf3df (PR #2052, merged 2026-06-12). Distro backports: Debian trixie 1.11.1-1+deb13u2, bookworm 1.10.0-3+deb12u1, sid 1.11.1-6; Ubuntu 26.04 1.11.1-1ubuntu0.26.04.2; SUSE 16.x 1.11.1-160000.4.1; openSUSE Tumbleweed 1.11.1-3.1. RHEL 8.1+ states not affected (libssh2 not a supported component). |
| Exposure Data | Shodan/Censys are not directly useful here — the vulnerability is client-side, not server-side. You cannot find vulnerable hosts by scanning SSH listeners. Asset inventory and SBOM analysis are the correct enumeration methods. Check ldd output or package manager queries for libssh2 linkage. |
| Disclosure | 2026-06-17 (VulnCheck published CVE). Fix merged upstream 2026-06-12. Public PoC dropped 2026-06-27 via exploitarium. Reporter: Tristan Madani (@TristanInSec). |
| Reporting Researcher | Tristan Madani (@TristanInSec), reported to VulnCheck. PoC separately published by bikini in the exploitarium archive (130+ unpatched PoCs across 22 projects). |
Sources.
Why this verdict
- Client-side-only attack surface: This is not a server-side vulnerability. The attacker cannot scan the internet for vulnerable libssh2 listeners and fire an exploit. The victim must initiate a connection to a malicious or compromised SSH endpoint. This single prerequisite eliminates the scan-and-exploit mass-exploitation pattern that drives CRITICAL urgency.
- MITM prerequisite implies prior position: For the most common exploitation scenario — intercepting an existing SSH connection — the attacker needs a network-level man-in-the-middle position (ARP spoof, DNS poison, BGP hijack). In enterprise networks, this typically implies the attacker already has internal access, making this a post-compromise escalation tool rather than an initial-access vector. SSH host-key verification (
known_hosts) further blocks MITM on established connections. - No in-the-wild exploitation and low EPSS: Despite the PoC being public since late June 2026, there are no confirmed exploitation incidents, no KEV listing, and EPSS sits at 0.825% — all consistent with the friction the client-side vector creates. The PoC is a scaffold, not a weaponized exploit.
- Heap exploitation complexity on modern systems: While the integer overflow is deterministic, achieving reliable code execution requires heap layout control. ASLR on 64-bit systems, glibc safe-linking (2.32+), and varying allocator behaviors across applications (curl vs. PHP vs. Git) increase the attacker's development cost for each target application.
- Role multiplier — CI/CD and backup agents (HIGH floor): libssh2 is present on CI/CD runners (Git for Windows, curl-based deploy scripts) and backup agents that SSH to remote hosts. If an attacker compromises a Git hosting endpoint or poisons a CI pipeline's SSH target, this vulnerability enables supply-chain-scale compromise. This role represents a meaningful fraction (>1%) of libssh2's installed base, setting a HIGH floor that prevents further downgrade despite the friction. On canonical CI/CD infrastructure, a successful chain leads to code-signing key theft, artifact tampering, or fleet-wide deployment of malicious builds.
- Role multiplier — workstations and general servers (MEDIUM-equivalent): On developer workstations and general-purpose servers, the blast radius is limited to the compromised process context. This role represents the majority of libssh2 installations but does not elevate beyond HIGH because the prerequisite chain remains intact.
Why not higher?
The vendor's 9.2 CRITICAL (CVSS 4.0) and even the 8.1 HIGH (CVSS 3.1) overstate the real-world risk because they underweight the client-side prerequisite. A CRITICAL rating is reserved for scan-and-exploit server-side flaws or vulnerabilities in canonically high-value components where the component *itself* defines the high-value role (e.g., a hypervisor escape, a domain controller auth bypass). libssh2 is a widely-used *library* that appears on high-value hosts, but it is not the role-defining component — exploiting it still requires the attacker to first solve the harder problem of controlling what SSH server the victim connects to.
Why not lower?
The public PoC, the deterministic integer overflow primitive, and the presence of libssh2 on CI/CD and backup infrastructure create a credible supply-chain and lateral-movement risk that floors this at HIGH. Downgrading to MEDIUM would ignore the realistic scenario where an attacker who compromises a single Git hosting server or internal SSH bastion can pivot to every libssh2-linked client that connects. The absence of an official upstream release also means many systems will remain vulnerable longer than usual, extending the exploitation window.
Crowdsourced verification payload.
Run this script on each target host as any user with read access to system binaries. It checks whether the installed libssh2 package contains the fix for CVE-2026-55200. Invoke with: bash check_cve_2026_55200.sh
#!/usr/bin/env bash
# check_cve_2026_55200.sh — Detect CVE-2026-55200 (libssh2 OOB write)
# Run on: target Linux host
# Privileges: none (read-only package queries)
# Exit codes: 0=PATCHED, 1=VULNERABLE, 2=UNKNOWN
set -euo pipefail
CVE="CVE-2026-55200"
FIXED_COMMIT="97acf3df"
VULN_MAX="1.11.1"
echo "[$CVE] Checking libssh2 installation..."
# Detect package manager and query version
PKG_VER=""
if command -v dpkg-query &>/dev/null; then
PKG_VER=$(dpkg-query -W -f='${Version}' libssh2-1 2>/dev/null || true)
if [ -z "$PKG_VER" ]; then
PKG_VER=$(dpkg-query -W -f='${Version}' libssh2-1t64 2>/dev/null || true)
fi
PKG_MGR="dpkg"
elif command -v rpm &>/dev/null; then
PKG_VER=$(rpm -q --qf '%{VERSION}-%{RELEASE}' libssh2 2>/dev/null || true)
PKG_MGR="rpm"
elif command -v pacman &>/dev/null; then
PKG_VER=$(pacman -Q libssh2 2>/dev/null | awk '{print $2}' || true)
PKG_MGR="pacman"
else
PKG_MGR="unknown"
fi
if [ -z "$PKG_VER" ]; then
# Check if libssh2 is present as a shared library at all
if ldconfig -p 2>/dev/null | grep -q libssh2; then
echo "[$CVE] libssh2 shared library found but package version unknown."
echo "[$CVE] Library path: $(ldconfig -p | grep libssh2 | head -1)"
echo "UNKNOWN"
exit 2
else
echo "[$CVE] libssh2 is not installed on this system."
echo "PATCHED"
exit 0
fi
fi
echo "[$CVE] Detected libssh2 version: $PKG_VER (via $PKG_MGR)"
# Check for known-patched distro versions
patched=false
case "$PKG_MGR" in
dpkg)
# Debian/Ubuntu backport versions that contain the fix
if echo "$PKG_VER" | grep -qE 'deb12u[1-9]'; then
patched=true
elif echo "$PKG_VER" | grep -qE 'deb13u[1-9]'; then
patched=true
elif echo "$PKG_VER" | grep -qE 'ubuntu0\.(26|25)\.[0-9]+\.[2-9]'; then
patched=true
elif dpkg --compare-versions "$PKG_VER" ge "1.11.1-3" 2>/dev/null; then
patched=true
fi
;;
rpm)
# SUSE/openSUSE fixed versions
if echo "$PKG_VER" | grep -qE '160000\.4\.[1-9]'; then
patched=true
elif echo "$PKG_VER" | grep -qE '1\.11\.1-3'; then
patched=true
fi
# RHEL 8.1+ reportedly not affected
if [ -f /etc/redhat-release ]; then
RHEL_VER=$(grep -oP '[0-9]+\.[0-9]+' /etc/redhat-release | head -1)
if [ -n "$RHEL_VER" ]; then
MAJOR=$(echo "$RHEL_VER" | cut -d. -f1)
MINOR=$(echo "$RHEL_VER" | cut -d. -f2)
if [ "$MAJOR" -ge 9 ] || { [ "$MAJOR" -eq 8 ] && [ "$MINOR" -ge 1 ]; }; then
echo "[$CVE] RHEL $RHEL_VER — Red Hat states libssh2 is not a supported component."
echo "[$CVE] Verify with: rpm -q libssh2 and check Red Hat advisory."
echo "PATCHED"
exit 0
fi
fi
fi
;;
esac
if $patched; then
echo "[$CVE] Installed version $PKG_VER contains the backported fix."
echo "PATCHED"
exit 0
fi
# Generic version comparison — anything <= 1.11.1 without a backport suffix is vulnerable
UPSTREAM_VER=$(echo "$PKG_VER" | grep -oP '^[0-9]+\.[0-9]+\.[0-9]+' || true)
if [ -z "$UPSTREAM_VER" ]; then
echo "[$CVE] Cannot parse upstream version from: $PKG_VER"
echo "UNKNOWN"
exit 2
fi
# Compare versions (1.11.2 or higher would contain the fix if released)
IFS='.' read -r MAJ MIN PAT <<< "$UPSTREAM_VER"
if [ "$MAJ" -lt 1 ] || { [ "$MAJ" -eq 1 ] && [ "$MIN" -lt 11 ]; } || \
{ [ "$MAJ" -eq 1 ] && [ "$MIN" -eq 11 ] && [ "$PAT" -le 1 ]; }; then
echo "[$CVE] Version $UPSTREAM_VER is <= $VULN_MAX and no backport detected."
echo "VULNERABLE"
exit 1
else
echo "[$CVE] Version $UPSTREAM_VER is newer than $VULN_MAX."
echo "PATCHED"
exit 0
fi