HIGHSecurity · SSH client library · Heap-overflow RCE + pre-auth DoS · Dependency · June 2026 CVE-2026-55200 (CVSS 9.2) · CVE-2026-55199 (CVSS 8.2) · No fixed release

libssh2 Client-Side Heap-Overflow RCE (CVE-2026-55200) and Pre-Auth DoS (CVE-2026-55199): No Fixed Release Yet, Pin to the Patch Commits

By NewMaxx /June 23, 2026

Two vulnerabilities in libssh2, the widely embedded client-side SSH library that ships inside curl/libcurl, many Git builds, the PHP ssh2 extension, and assorted router/IoT and infrastructure management tooling, were published to the GitHub Advisory Database and NVD on June 16-17, 2026, credited to Tristan Madani (@TristanInSec). CVE-2026-55200 (CVSS 9.2, the NVD rates it CRITICAL) is an out-of-bounds heap write in ssh2_transport_read() that fails to bound the packet_length field: a malicious or machine-in-the-middle SSH peer can send a crafted packet with an oversized length, corrupt heap memory, and potentially achieve remote code execution in the process linking libssh2. CVE-2026-55199 (CVSS 8.2, HIGH) is a pre-auth denial of service in the SSH_MSG_EXT_INFO handler in src/packet.c: a malicious server can set the extension count to 0xFFFFFFFF during key exchange and pin the client in a CPU loop for over a minute. All libssh2 releases through 1.11.1 are affected, and as of this writing there is no fixed release tag. The fixes exist only as commits on the master branch (97acf3df for the RCE, 17626857 for the DoS). There are no public reports of in-the-wild exploitation. The most useful operator action is an inventory pass: find what links libssh2 in your fleet, and track your distro's patched build or pin to the fix commits.

Framing note: libssh2 is a client library. It is not OpenSSH and it is not a server. The realistic threat model is your software reaching out over SSH and connecting to a server that is attacker-controlled or sits behind a machine-in-the-middle position, not an attacker hitting your sshd from the internet. The CVSS vectors reflect this: both carry AT:P (Attack Requirements: Present), meaning the precondition is a libssh2 client establishing a session to the malicious endpoint. Several aggregator headlines describing this as thousands of internet-exposed systems open to unauthenticated RCE conflate it with server-side exposure and overstate it. That does not make it harmless: automation that clones over SSH, fetches via SCP/SFTP, or polls network devices through libssh2 can be pointed at a hostile or spoofed host, and the impact then lands in whatever process holds the library.

Why this is a bulletin, not a footnote

Three things make it worth an inventory pass now rather than waiting for a tagged release: (1) libssh2 is a deep transitive dependency. Most operators do not have it on a mental patch list, yet it rides inside curl, Git's SSH transport on many platforms, language bindings, and embedded management agents, so the exposure is wider than the package name suggests. (2) CVE-2026-55200 is a heap out-of-bounds write reachable before authentication completes, triggered by data the remote peer fully controls. Heap-overflow-to-RCE is not guaranteed in every build (allocator hardening, ASLR, and platform mitigations all matter), but the vendor advisories and NVD treat code execution as the realistic worst case, and it is best to assume it on unhardened or embedded targets. (3) There is no fixed release. libssh2 1.11.1 is still the latest tag; the fixes are commits on master. That means "just upgrade to the patched version" is not yet an option from upstream directly, and you are dependent on either your distribution's backport or a pinned build from the fix commits.

Affected versions, fix commits, and CVSS
Affected: libssh2 <= 1.11.1 (all releases up to and including 1.11.1) Not fixed in any tagged release as of 2026-06-23. Fixes live only on the master branch. CVE-2026-55200 (CRITICAL, the RCE) Type: Out-of-bounds write / heap corruption CWE-680 Integer Overflow to Buffer Overflow Where: ssh2_transport_read() in src/transport.c Cause: packet_length field not bounded before use; oversized value drives an OOB heap write. Impact: heap corruption -> potential remote code execution Trigger: crafted SSH packet from the peer (malicious or MITM server), pre-authentication. CVSS: 9.2 CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:N/ VC:H/VI:H/VA:H/SC:N/SI:N/SA:N Fix: commit 97acf3dfda80c91c3a8c9f2372546301d4a1a7a8 (PR libssh2/libssh2#2052) Note: the CVE description abbreviates this commit as "7acf3df"; the actual short hash is 97acf3df. CVE-2026-55199 (HIGH, the DoS) Type: Pre-auth denial of service CWE-835 Loop with Unreachable Exit Condition Where: SSH_MSG_EXT_INFO handler in src/packet.c Cause: nr_extensions can be set to 0xFFFFFFFF during key exchange; return values from _libssh2_get_string() are unchecked and the session timeout does not apply to CPU-bound loops. Impact: client CPU exhaustion, tight loop for 60+ seconds (availability only; no confidentiality/integrity) Trigger: malicious SSH server during key exchange, pre-authentication. CVSS: 8.2 CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:N/ VC:N/VI:N/VA:H/SC:N/SI:N/SA:N Fix: commit 17626857d20b3c9a1addfa45979dadcee1cd84a4 (PR libssh2/libssh2#1864) Credit: Tristan Madani (@TristanInSec) Disclosed: 2026-06-16 (VulnCheck), published 2026-06-17 (GitHub Advisory Database, NVD) Distro status (spot-checked, verify against your own distro): Debian: 1.11.1-3 reported in testing per the Debian Security Tracker. Kali: 1.11.1-3 reported present since ~May 2026. Others: track your distribution's security tracker; many had not shipped a fixed package at time of writing.
Sources: GitHub Advisory Database GHSA-r8mh-x5qv-7gg2 and GHSA-3cfq-4xx4-rmpg, the matching NVD records, and the two VulnCheck advisories. CVSS vectors and the CWE mappings are taken from VulnCheck; the 9.2 and 8.2 base scores match the GitHub Advisory Database. The distro lines are spot checks from the Debian Security Tracker and Kali package pages and are not a comprehensive cross-distro matrix. Verify the fixed package version for your own distribution before relying on a backport, because backport version strings differ and the upstream 1.11.1 string alone does not tell you whether the two fix commits are included.

Priorities, by how you use libssh2

Triage on two questions: does any of your software link libssh2 as a client, and does that client ever connect to an SSH endpoint you do not fully trust (a third-party host, a device on an untrusted segment, anything reachable across a network an attacker could occupy for a machine-in-the-middle). The closer you are to "yes, yes," the higher this rises.

Priority Use of libssh2 Why
Higher libssh2 client connecting to endpoints you do not control, or across untrusted networks (CI/CD that clones or deploys over SSH to external hosts, SCP/SFTP fetches from third parties, automation that polls customer or field devices) This is the exposure pattern CVE-2026-55200 reaches. The peer controls the packet that triggers the OOB write, and the trigger fires before authentication, so trusting the server's credentials does not help you. A compromised or spoofed endpoint, or a MITM on the path, can attempt heap corruption against the process holding libssh2. Inventory now, track the patched build, and pin trusted host keys so a MITM cannot transparently substitute a hostile server.
Higher Embedded / appliance / IoT firmware that bundles its own libssh2 to manage or reach other devices Embedded builds are the worst case for heap-overflow-to-RCE: frequently no ASLR, weak or no allocator hardening, long patch latency, and a copy of libssh2 statically linked or vendored into firmware where your distro's backport never reaches. If a field device's management agent connects out through libssh2, treat it as exposed until the vendor ships fixed firmware, and constrain which endpoints it will dial.
Medium curl/libcurl, Git, PHP ssh2, or language bindings on servers and workstations, used against mostly trusted hosts Still affected, lower realized risk because the endpoints are usually your own infrastructure. The exposure is the day someone points one of these at a hostile or spoofed host (a malicious repo URL, a typo-squatted hostname, a poisoned CI variable). Patch on your normal package cadence once the fixed build lands, and prefer host-key verification everywhere.
Medium Anything where the only realistic exposure is the DoS (CVE-2026-55199) against a client that connects to semi-trusted servers Availability-only impact: a malicious or compromised server can stall the client for a minute-plus per connection. Annoying for an interactive tool, more material for automation that opens many sessions or runs on a tight schedule. Same fix; lower urgency than the RCE if the RCE path does not apply to you.
Lower Systems that do not link libssh2 at all, or that only run an OpenSSH/libssh server (not libssh2) Not affected by these two CVEs. libssh2 is a separate project from OpenSSH and from libssh (the libssh.org library). Confirm you actually have no libssh2 in the dependency graph (see the inventory commands below) before concluding you are clear, because it arrives transitively more often than people expect.

Categorization source: this prioritization is the bulletin's own framing, derived from the CVSS vectors (both AV:N/AC:L/AT:P/PR:N/UI:N, RCE vs. availability-only impact) and the client-side nature of the library. It is not an upstream-published severity ranking beyond the base CVSS scores.


Am I affected?

Find libssh2 in your packages (Linux)

Start with the package manager, then widen to linked binaries and vendored copies. On Debian/Ubuntu:

dpkg -l | grep -i libssh2
apt-cache policy libssh2-1

On RPM-based systems (RHEL, Fedora, SUSE). The glob catches distro-specific names such as libssh2-1 on SUSE, and the %{RELEASE} field is where a backported fix usually shows:

rpm -qa 'libssh2*'
rpm -qa --qf '%{NAME} %{VERSION}-%{RELEASE}.%{ARCH}\n' 'libssh2*'

Compare the installed version against your distribution's security tracker. The upstream string will read 1.11.1 or lower; a backported fix usually shows as a higher package revision (for example 1.11.1-3 on Debian) rather than a higher upstream version, so do not rely on the 1.11.1 string alone. Confirm the advisory entry for your distro lists both fix commits as included.

Find linked and vendored copies

Distro metadata misses statically linked and vendored copies. Look for the shared object on disk and for the processes currently holding it open:

ldconfig -p | grep -i libssh2
find / -xdev -name 'libssh2*' 2>/dev/null

To see which running processes currently hold it open:

lsof 2>/dev/null | grep -i libssh2

curl is the most common consumer. Its version banner lists libssh2 when the build links it:

curl --version | tr ' ' '\n' | grep -i ssh2

An empty result means this curl build does not link libssh2 (it may use OpenSSH-backed SCP differently, or omit SCP/SFTP support). A line like libssh2/1.11.1 means it does, at that version.

Language bindings and app dependencies

Bindings wrap the same C library and inherit the bug. Check the ones you use:

pip list 2>/dev/null | grep -i ssh2
php -m | grep -i ssh2
php -r 'echo phpversion("ssh2");' 2>/dev/null

For the Python ssh2-python binding and similar, the relevant question is which libssh2 it was built or bundled against; a wheel can carry its own copy. For Git, builds vary by platform on whether the SSH transport uses an external ssh binary or a linked libssh2 (often via libgit2), so confirm your specific Git build rather than assuming.

Windows and macOS

On Windows, libssh2 most often arrives bundled inside a vendored build of curl, Git for Windows, or a third-party application, rather than as a system package, so inventory means checking the application's own version banner or its shipped DLLs (libssh2.dll). On macOS, Homebrew's brew info libssh2 shows the formula version, but applications frequently vendor their own copy independent of Homebrew. In both cases the static/vendored-copy problem dominates: the fix arrives when each application ships an updated build, not when a shared system library is patched.


Response

  1. Inventory first, patch second. Run the checks above across your fleet and build a list of every place libssh2 is linked, including curl, Git, PHP, language bindings, and any vendored or statically linked copies in applications and firmware. The dependency is transitive often enough that the inventory is the real work here; once you know where it is, the patching is routine. Prioritize the inventory by the priority table above: clients that dial untrusted endpoints and embedded agents first.
  2. Track your distribution's patched build and apply it when it lands. Because there is no upstream fixed release tag yet, the cleanest path for distro-packaged libssh2 is the backport. Watch your distro's security tracker for the package that lists both fix commits (97acf3df and 17626857), then update on your normal cadence. Debian's tracker showed 1.11.1-3 in testing at time of writing; confirm the current state for your release rather than trusting this snapshot. If you maintain your own build of libssh2 from source, you can cherry-pick or build from master past both fix commits now rather than waiting for a tag, but pin to a known-good commit and test, since master is not a release.
  3. Verify SSH host keys everywhere a libssh2 client connects. Both bugs require the client to talk to a hostile server. Strict host-key checking (a known-hosts pin, certificate verification, or equivalent in whatever wraps libssh2) is what stops a machine-in-the-middle from transparently swapping in an attacker-controlled server on the path. This is a mitigation that works today, independent of the patch, and is good practice regardless. Confirm your automation is not configured to blindly accept unknown host keys.
  4. Constrain where untrusted-facing and embedded clients can connect. For automation and field/IoT agents that reach out through libssh2, limit the set of endpoints they will dial (egress allow-lists, fixed target hosts, network segmentation) so a single poisoned URL or compromised endpoint has a smaller chance of steering a vulnerable client at a hostile server. This narrows the attack surface during the window before every vendored copy is patched.
  5. For vendored and firmware copies, open vendor tickets. Where libssh2 is statically linked into a third-party application or device firmware, your distro backport will never reach it; the fix arrives only when the vendor rebuilds. Identify those products from the inventory, ask each vendor for a build that includes both fix commits, and treat the device or app as exposed in the meantime if it connects out to anything you do not control.
  6. Watch for a tagged release and for any exploitation signal. A libssh2 release past 1.11.1 that carries both commits is the clean fix for source builds and downstreams; track the project's releases page. There is no confirmed in-the-wild exploitation and no public PoC at time of writing; if that changes, the RCE's pre-auth, peer-controlled trigger makes it worth re-prioritizing, so keep an eye on the CISA KEV catalog and vendor advisories.

The broader pattern

The recurring lesson here is not about SSH specifically, it is about transitive C dependencies that nobody has on a patch list. libssh2 sits one or two layers below the tools operators actually think about, so the hard part of responding is discovery, not remediation. The same shape has shown up repeatedly: a memory-safety bug in a small, ubiquitous C library (the kind that gets vendored into curl, into language runtimes, into appliance firmware) where the real cost is finding all the copies, and the long tail is the statically linked and firmware-embedded instances that a distribution update never touches.

It also reinforces a calibration point worth keeping: a 9.2 CRITICAL on a client library is a different risk than a 9.2 on an internet-facing server. The pre-auth label is real, but "pre-auth" here means the client is attacked before it authenticates the server, so the precondition is reaching out to a hostile peer, not sitting exposed waiting to be hit. Host-key verification, egress control, and knowing your dependency graph are the controls that actually move this risk, and they are available before any patch ships.

Caveats and unknowns

At time of writing: there is no upstream fixed release tag, only the two master commits, so version strings alone are an unreliable signal of whether a given build is patched; verify commit inclusion. There is no confirmed in-the-wild exploitation and no public proof-of-concept. Whether CVE-2026-55200 reliably reaches code execution as opposed to a crash depends heavily on the target's allocator, platform mitigations, and build hardening; the advisories assert RCE as the realistic worst case and this bulletin follows that, but a given build may only be DoS-able in practice. The distro status lines are spot checks (Debian, Kali) and not a complete cross-distribution matrix; check your own distribution. CISA had not listed either CVE in the KEV catalog as of publication. The CVE description's abbreviated commit hash ("7acf3df") does not match the actual short hash (97acf3df); this bulletin uses the full commit IDs from the pull requests to avoid ambiguity. This guide will be updated if a tagged release ships, if exploitation is reported, or if the cross-distro patch picture firms up.

One-line takeaway

libssh2 through 1.11.1 has a pre-auth heap-overflow RCE (CVE-2026-55200, CVSS 9.2) and a pre-auth DoS (CVE-2026-55199, CVSS 8.2), both triggered when a libssh2 client connects to a malicious or MITM SSH server, and both fixed only as master commits (97acf3df, 17626857) with no tagged release yet. Inventory everything that links libssh2 (curl, Git, PHP, bindings, vendored and firmware copies), track your distro's backported build or pin to the fix commits, and verify SSH host keys so a machine-in-the-middle cannot swap in a hostile server. No confirmed in-the-wild exploitation yet; prioritize inventory and patch tracking over emergency internet-exposure response.

All Bulletins ↑ Primary source: GitHub Advisory →