
Hoplon InfoSec
29 Jun, 2026
Content Summary
| Field | Detail |
|---|---|
| CVE ID | CVE-2026-55200 |
| CVSS 4.0 Score | 9.2 (Critical) |
| CWE | CWE-680 (Integer Overflow to Buffer Overflow) |
| Affected Versions | libssh2 all releases through 1.11.1 |
| Vulnerable Function | ssh2_transport_read() in transport.c |
| Attack Vector | Network, Pre-authentication, No user interaction required |
| Impact | Heap memory corruption leading to arbitrary code execution |
| Disclosed | June 17, 2026 via VulnCheck |
| Fix Merged | June 12, 2026 (PR #2052, commit 97acf3d) |
| Official Release | No tagged release yet; distros backporting independently |
| Reported By | Security researcher Tristan Madani |
| PoC Status | Public (exploitarium repository, local harness only) |
| CISA KEV Status | None confirmed as of publish date |
| Companion CVEs | CVE-2026-55199 (CVSS 8.2, DoS) and CVE-2025-15661 (CVSS 8.3, SFTP heap over-read) |
Here is the thing about CVE-2026-55200 that most articles are not telling you: this is not a server vulnerability. It is a client-side attack. The victim is your SSH client, your curl binary, your Git installation, your PHP deployment, your backup agent sitting quietly on a production server anything that uses libssh2 and reaches out to connect to an SSH endpoint you do not fully control. A single crafted packet from a malicious server is all it takes. No credentials. No user clicks. No warning.
CVE-2026-55200 libssh2 carries a CVSS 4.0 score of 9.2 and affects every version of the library released up to and including 1.11.1. Security researcher Tristan Madani reported it. The fix was merged into the mainline codebase on June 12, 2026, but no official tagged release exists yet. That means right now, today, the vast majority of systems running libssh2 are running a vulnerable version- and many of those systems do not even know libssh2 is installed on them.
That last point is the piece that keeps security teams up at night.
Most people have never heard of libssh2. That is exactly what makes this dangerous.
libssh2 is a C library that implements the SSH2 protocol on the client side. It is not a server daemon. It does not listen for connections. It helps other software make outbound SSH connections, file transfers, remote commands, and automated synchronisation. The library itself is embedded inside dozens of widely deployed tools, including cURL, Git (through libgit2), PHP's ssh2 PECL extension, backup agents, firmware updaters, IoT devices, and network appliances.
When you update your system's libssh2 package through apt or yum, you patch the copy your OS knows about. But many of those tools above ship their own statically compiled copy of libssh2 baked directly into their binary. The package manager has no idea those copies exist. They will not be updated by a system-level patch. They will sit there, vulnerable, until the vendor of that specific tool ships an updated binary.
This is what security people call a 'software supply chain risk': one library buried deep inside many products, each of which needs its own independent fix. It is a slow and uneven process even in the best circumstances.
| Software | Embedding Method | Update Path |
|---|---|---|
| curl | Dynamic (most distros) | OS package manager |
| Git / libgit2 | Dynamic or bundled | OS or application update |
| PHP ssh2 extension | Dynamic | PHP/PECL update |
| Backup agents | Often statically linked | Vendor advisory required |
| IoT / network firmware | Statically compiled in firmware | Vendor firmware release |
| CI/CD tooling | Vendored or containerized | Container image rebuild |
An organisation can have the OS-level libssh2 package fully patched and still be completely exposed through a statically linked backup agent or a containerised CI/CD tool pulling from an unpatched base image.
Let me walk you through exactly how this bug works, because the technical details here are genuinely interesting, and understanding them is what separates a security team that can properly calibrate risk from one that just pastes an advisory into a ticket and closes it.
When two SSH endpoints connect, the very first thing that happens is a handshake before any credentials are exchanged, before any authentication step occurs. During this handshake, the server and client pass binary packets back and forth following a strict format:
[4-byte packet_length][1-byte padding_length][payload][padding][optional MAC]
The packet_length field is a 4-byte integer that the server sends to tell the client how many bytes follow. The client reads this value and uses it to decide how much memory to allocate for the incoming packet. The server fully controls what value goes in that field.
In a legitimate connection, this is fine. In a connection to a malicious or compromised server, this is a problem.
libssh2's ssh2_transport_read() function in transport. C is responsible for parsing these incoming packets. In every version through 1.11.1, the function only rejected packet_length values below 1. It had no upper bound check. None.
Here is what the vulnerable size calculation looks like in pseudocode:
total_num = 4;
total_num += packet_length + mac_len + auth_len; // 32-bit arithmetic
// Only reject if total_num > 35000 or total_num == 0
allocate total_num bytes;
Now watch what happens when an attacker sends packet_length = 0xffffffff (the maximum 32-bit unsigned integer value), with mac_len = 0 and auth_len = 16:
0xffffffff + 0 + 16 = 15 (modulo 2³² – the value wraps around)
4 + 15 = 19
The allocator receives a request for 19 bytes. It happily allocates 19 bytes. But the code that processes the packet afterwards still operates using sizes derived from the original packet_length value, the huge one. So you end up with a 19-byte buffer that the code then tries to write a full, oversized packet into. That is an out-of-bounds heap write, classified under CWE-680 (Integer Overflow to Buffer Overflow).
This class of primitive is one of the most reliable starting points for building a working exploit. Overwriting adjacent heap structures with controlled data is a well-understood technique for achieving code execution.
The fix is straightforward once you understand the bug. Before the vulnerable arithmetic runs, the patched code adds a single guard:
if (packet_length > LIBSSH2_PACKET_MAXPAYLOAD) {
// reject and disconnect
}
That one check, applied before the 32-bit addition, eliminates the entire overflow path. The same LIBSSH2_PACKET_MAXPAYLOAD constant was used to fix a near-identical vulnerability in 2019 (more on that below) – it simply was never applied to this particular code path in transport. c. The fix was merged in PR #2052 on June 12, 2026, and Vuln Check published the CVE five days later, on 17 June.
| Condition | Pre-Patch (libssh2 through 1.11.1) | Post-Patch (commit 97acf3d) |
|---|---|---|
| Lower bound check | Reject if packet_length < 1 | Retained |
| Upper bound check | None | Reject if > LIBSSH2_PACKET_MAXPAYLOAD |
| 32-bit integer overflow path | Present and exploitable | Eliminated before math executes |
| Attacker-controlled heap allocation | Yes | No |
The Public Proof of Concept: What It Proves and What It Does Not
A public proof of concept for this libssh2 heap overflow was published in the "exploitarium" repository on GitHub by a researcher operating under the handle "bikini". The repository was released without prior vendor notification, which immediately drew criticism from the security community, especially given the CVSS 9.2 rating and the absence of an official patched release at the time of disclosure.
The repository includes four research artefacts:
cve_2026_55200_probe.c is a standalone C11 arithmetic verifier. It does nothing but demonstrate that the integer wrap condition is real and reproducible. You compile it and run it; it shows you the math working exactly as described above.
libpwn_cve_2026_55200_server.py is a malicious Python SSH server scaffold. It negotiates a real SSH handshake – a curve25519-sha256 key exchange, RSA host key authentication and chacha20-poly1305@openssh.com encryption – and then sends a malformed encrypted packet whose decrypted packet_length value is 0xffffffff. This is the trigger. It is locally verified to cause the vulnerable allocation path to execute.
libpwn_local_rce_harness.c is a controlled vulnerable target that models the wrapped allocation-to-control pattern. It simulates what happens after the 19-byte allocation is created: the exploit overflows from that buffer into an adjacent callback pointer.
libpwn_local_rce_exploit.py is the local exploit driver. It connects the server scaffold to the harness, overflows the callback pointer, and creates a proof file on disc to confirm code execution. The researcher's evidence log from June 23, 2026, shows this working in a local environment.
This is the part most coverage gets wrong. The exploitarium PoC is a local research harness, not a turnkey remote exploit. It proves the arithmetic wrap is real. It demonstrates the out-of-bounds write primitive in a controlled local context. It does not give an attacker a working exploit against a production curl binary, a real PHP deployment, or any specific libssh2-embedding application.
Turning a local harness into a reliable remote exploit requires defeating ASLR, accounting for the specific heap layout of the target allocator (glibc, musl, jemalloc), understanding exactly how that application embeds libssh2, and building a working overwrite chain for that specific binary. That is non-trivial work. It can be done, especially with a public PoC as a starting point, but it is not done yet based on everything publicly available as of this writing.
| Risk Factor | Assessment |
|---|---|
| CISA Known Exploited Vulnerabilities listing | Not listed (no confirmed in-the-wild exploitation) |
| PoC type | Local harness — not a universal remote exploit |
| CVSS Attack Complexity | Low (when conditions align in a specific deployment) |
| Real-world exploitation difficulty | Medium to high depending on target binary and mitigations |
| Weaponization timeline risk | Elevated; public PoC + local harness accelerates research significantly |
The absence of confirmed in-the-wild exploitation right now does not mean the window is comfortable. A public PoC shortens the weaponisation timeline for any skilled attacker willing to put in the adaptation work.
Here is something none of the other articles about this vulnerability are telling you: we have been here before, in the same function, with the same class of bug.
In March 2019, libssh2 released version 1.8.1 to fix CVE-2019-3855. That vulnerability was an unchecked integer overflow in ssh2_transport_read(), an attacker-controlled packet_length value missing upper bound validation, resulting in a malicious SSH server being able to execute code on a connecting client. The fix was to enforce LIBSSH2_PACKET_MAXPAYLOAD as an upper bound before processing. Chris Coulson originally reported it to the libssh2 project in December 2018.
Seven years later, CVE-2026-55200 is the same CWE class, the same function, and the same missing upper-bound guard, just in a different code path inside that function. The LIBSSH2_PACKET_MAXPAYLOAD check introduced in 2019 was applied to one path. It was never applied to the full-packet decryption branch. That second path sat unprotected for seven years.
| Attribute | CVE-2019-3855 | CVE-2026-55200 |
|---|---|---|
| Year disclosed | 2019 | 2026 |
| Vulnerable function | ssh2_transport_read() in transport.c | ssh2_transport_read() in transport.c |
| Root cause | Missing upper bound on packet_length | Missing upper bound on packet_length (different code path) |
| CWE classification | CWE-130 / CWE-190 | CWE-680 |
| Reported by | Chris Coulson | Tristan Madani |
| Fix mechanism | LIBSSH2_PACKET_MAXPAYLOAD guard | LIBSSH2_PACKET_MAXPAYLOAD guard |
| Fixed in | libssh2 1.8.1 (official release) | Commit 97acf3d (no official tagged release yet) |
libssh2 has 18 published CVEs since 2015. Out-of-bounds reads (CWE-125) and integer overflows (CWE-190) are its two most frequently appearing weakness categories. This is not a one-time mistake. It is a pattern in how the codebase handles attacker-controlled length fields. Security teams auditing their exposure should treat this as a signal about the library's overall input validation posture, not just an isolated incident to patch and forget.
CVE-2026-55200 was disclosed alongside two companion vulnerabilities. Most coverage mentions them in a single sentence. They each deserve proper explanation because each one represents a different attack scenario with different mitigation priorities.
This one is in packet.c, inside the SSH_MSG_EXT_INFO handler. During the SSH key exchange phase, which, again, happens before any authentication, the server can advertise a list of extensions it supports. It sends a count of how many extensions follow, and then libssh2 loops over that count to process each advertised extension.
The problem is that libssh2 never validates the extension count before entering the loop. An attacker sends an absurdly large count value. libssh2 starts looping. It keeps looping. It loops for over 60 seconds in tested scenarios, fully pegging the CPU of the connecting client process.
For automated systems, CI/CD pipelines running dozens of concurrent SSH connections, backup agents firing every few minutes, and monitoring daemons polling remote hosts, this is a serious operational problem. The fix is commit 1762685, which adds a sanity check on the extension count before the loop begins.
This vulnerability lives in sftp_symlink() inside sftp.c and is triggered when a client performs SFTP READLINK or REALPATH operations. A malicious server (or an attacker positioned as a man-in-the-middle on what the client thinks is a trusted connection) sends a crafted SSH_FXP_NAME response with an oversized link_len value. libssh2 reads past the end of the allocated buffer, resulting in potential information disclosure from heap memory or a crash.
This one requires the client to initiate an SFTP symlink operation, so it is not pre-authentication like the other two. But a man-in-the-middle attacker on a trusted SSH channel can trigger it without the client suspecting anything. CloudLinux is tracking the fix for their alt-libssh2 package internally under ALTPHP-2484.
| CVE | CVSS | Type | Trigger Phase | Vulnerable Location | Impact |
|---|---|---|---|---|---|
| CVE-2026-55200 | 9.2 Critical | Out-of-bounds heap write | Pre-authentication handshake | transport.c / ssh2_transport_read() | Remote code execution |
| CVE-2026-55199 | 8.2 High | CPU exhaustion infinite loop | Pre-authentication key exchange | packet.c / SSH_MSG_EXT_INFO handler | Denial of service |
| CVE-2025-15661 | 8.3 High | Heap over-read | Post-authentication SFTP operations | sftp.c / sftp_symlink() | Information disclosure or crash |
This is the section that most security teams need most, and almost no coverage provides it with enough operational detail.
Running apt list --installed | grep libssh2 or rpm -qa | grep libssh2 will show you the copies your operating system manages. It will not show you the copy compiled into your backup agent. It will not show you the version baked into your network appliance firmware. It will not show you the libssh2 embedded in a containerised CI/CD runner your team built two years ago and never updated.
These invisible copies are the ones that will get you.
# Debian/Ubuntu - check the installed package
dpkg -l | grep libssh2
# RHEL/CentOS/Rocky - check installed packages
rpm -qa | grep libssh2
# Find all binaries currently linking libssh2 dynamically
find / -name "*.so*" | xargs grep -l "libssh2" 2>/dev/null
ldd /usr/bin/curl | grep libssh2
# Search for libssh2 strings embedded in compiled binaries
find /usr /opt /srv -type f -executable \
| xargs strings 2>/dev/null | grep -i "libssh2"
# Check a specific binary for the vulnerable function symbol
nm -D /path/to/binary | grep ssh2_transport_read
objdump -p /path/to/binary | grep libssh2
If your environment uses containers, scanning the filesystem inside images is the only reliable way to catch statically linked copies:
# Trivy - scan a container image for critical CVEs
trivy image <image_name> --severity CRITICAL.
# Grype - check for libssh2 specifically
grype <image_name> | grep libssh2
# Syft - generate an SBOM and filter for libssh2
syft <image_name> -o json | jq '. artefacts[] | select(.name=="libssh2")'
Your vulnerability management process should treat any binary that contains 'ssh2_transport_read' as a potentially vulnerable artefact until verified otherwise. Nessus has dedicated detection plugins for CVE-2026-55200 that can assist with asset discovery across your environment.
curl binaries inside containers and appliances
Git distributions bundled in CI/CD runners
PHP installations with the ssh2 PECL extension enabled
Vendor-supplied backup software agents (especially those that use SFTP or SCP)
Network appliance firmware (requires monitoring your vendor's advisory channel)
Understanding your attack surface management posture here matters more than average, because libssh2's attack surface is distributed across tools and vendors, not concentrated in a single package.
The honest starting point is acknowledging the awkward situation: there is no official tagged libssh2 release containing the fix yet. The patch exists in the mainline branch as commit 97acf3d, and Linux distributions and downstream projects are backporting it themselves. This is not unusual for open-source projects, but it does mean you cannot simply wait for "libssh2 version X.Y.Z" to appear and update to it. You need to track your specific distribution's advisory channel.
| Distribution | Status | Notes |
|---|---|---|
| Debian | Backport in testing | Repaired build already available |
| RHEL 8/9 | Not directly affected | libssh2 not in base repo; EPEL users must check upstream |
| CloudLinux 7 | ELS coverage in progress | Do not remove — required by alt-libcurl and alt-php |
| CloudLinux 8/9 | Not affected (follows RHEL policy) | alt-libssh211 patch tracked internally as ALTPHP-2484 |
| CloudLinux 10 | libssh2 not provided | Not applicable |
| Ubuntu | Check ubuntu-security-announce | Monitor distro advisory tracker |
| Upstream source | Commit 97acf3d in mainline | No official tagged release yet |
Run static linking detection across all hosts, containers, and network appliances using the commands above
Apply a build containing commit 97acf3d use your distro's backport if available, or build from patched source
Apply commit 1762685 for CVE-2026-55199 at the same time – do not patch one and leave the other open.
Apply the upstream SFTP fix for CVE-2025-15661
Track your specific vendor's advisory channel for every product that might embed libssh2.
Verify SSH host keys on every endpoint your infrastructure connects to
Prioritise any client that reaches external SSH servers or resolves hostnames that could be redirected via DNS
Not everything can be patched instantly. Here is how to reduce exposure while waiting:
Restrict outbound SSH connections to known trusted server IPs using firewall rules. If a tool only needs to reach one internal server, block everything else at the network layer.
Enforce strict SSH host key verification everywhere. Find every configuration file in your environment containing StrictHostKeyChecking no and change it. An attacker needs the client to connect to a server they control – host key verification is the easiest way to prevent that from working silently.
Monitor SSH traffic for oversized packet anomalies. A packet_length value of 0xffffffff or any value approaching that range in SSH traffic is a clear indicator of an exploitation attempt.
Watch for unexplained crashes in curl, git, or PHP processes following SSH connection attempts. A failed exploitation attempt often produces a segmentation fault. Crash dumps from libssh2-using applications are a detection signal worth capturing.
For automated pipelines, temporarily gate or disable any pipeline step that connects to an external SSH server until the underlying tool is patched. Your incident response and recovery plan should have a playbook for exactly this kind of interim containment scenario.
Understanding where CVE-2026-55200 sits in the ATT&CK framework helps security teams prioritise detection and response coverage:
| ATT&CK Technique | Technique ID | Application to CVE-2026-55200 |
|---|---|---|
| Exploit Public-Facing Application | T1190 | Relevant if a libssh2-using service is internet-reachable |
| Exploitation for Client Execution | T1203 | Primary technique: malicious server exploits connecting client |
| Supply Chain Compromise | T1195 | Statically linked libssh2 inside third-party software |
| Man-in-the-Middle | T1557 | Attacker intercepts SSH handshake to inject malicious packet_length |
| Compromise Infrastructure | T1584 | Attacker compromises a legitimate SSH server the target trusts |
The T1203 mapping is the critical one. This is fundamentally a client exploitation vulnerability. The attacker's position is a server, not another client. That flips the typical mental model defenders use when thinking about SSH threats.
Your SIEM and IDS configurations should be updated to alert on SSH packets containing packet_length values at or near 0xFFFFFFFF. Most network detection systems can parse SSH protocol fields; this is a specific, unambiguous indicator.
Behavioural monitoring should flag unexplained crashes or core dumps in processes known to embed libssh2, curl, git, and PHP-FPM backup agent daemons, especially when those crashes coincide with SSH connection activity.
At the network layer, alert on outbound SSH connections to previously unseen destinations. A compromised DNS record redirecting your tools to an attacker-controlled server is one of the realistic attack scenarios here.
Nessus includes dedicated detection plugins for CVE-2026-55200 that scan for vulnerable libssh2 versions across your asset inventory. Running these against your full environment should be a first-week action.
NHS England Digital issued a formal advisory urging affected organisations to update, which speaks to the real-world urgency the security community has assigned to this vulnerability.
Your extended detection and response platform should have telemetry across the endpoint, network, and application layers needed to catch both exploitation attempts and successful compromises. Correlating crash signals with network connection events is the detection pattern most likely to surface active exploitation before it causes lasting damage.
For organisations that want an expert assessment of their exposure before committing to a full remediation campaign, penetration testing that includes SSH client-side attack scenarios will validate whether your specific deployments are reachable through this vector.
What is CVE-2026-55200?
CVE-2026-55200 is a critical severity (CVSS 9.2) out-of-bounds heap write vulnerability in libssh2's ssh2_transport_read() function inside transport. c. A malicious SSH server sends a crafted packet with packet_length = 0xffffffff, which causes a 32-bit integer overflow. The result is a 19-byte memory allocation, while the code writes a full oversized packet into it, enabling pre-authentication remote code execution on the connecting client with no credentials and no user interaction required.
Which libssh2 versions are affected?
All versions of libssh2 up to and including 1.11.1 are affected. There is no official fixed release yet. The patch exists in commit 97acf3d on the mainline branch. Individual Linux distributions are backporting this fix themselves; check your specific distribution's security advisory channel for current status.
What software uses libssh2 and is therefore at risk?
Curl; Git (through libgit2); PHP's ssh2 PECL extension; backup agents; firmware updaters; IoT devices; network appliances; and CI/CD tooling are the most common carriers. Many of these embed libssh2 as a statically compiled library, which makes them invisible to OS-level package managers and requires separate vendor patches.
Has CVE-2026-55200 been exploited in the wild?
As of the publish date of this article, CISA's Known Exploited Vulnerabilities catalogue shows no listing for CVE-2026-55200, and no confirmed in-the-wild exploitation has been reported. A public proof of concept exists in the exploitarium repository, but it functions as a local research harness rather than a turnkey remote exploit. The absence of confirmed exploitation should not be read as safety — it reflects the current state, not the future risk.
What is the difference between CVE-2026-55200 and CVE-2026-55199?
CVE-2026-55200 (CVSS 9.2) is a heap write flaw in transport. c that can lead to remote code execution, triggered during the SSH handshake before authentication. CVE-2026-55199 (CVSS 8.2) is a CPU exhaustion denial-of-service in packet.c, triggered by an unchecked extension count during the key exchange phase. Both are pre-authentication vulnerabilities disclosed in the same batch. Both should be patched simultaneously.
How do i find statically linked copies of libssh2 that my package manager cannot see?
Use strings on executable files and search for "libssh2" identifiers, or use nm and objdump to check for the presence of the ssh2_transport_read symbol in a specific binary. Container and image scanning tools like Trivy, Grype, and Syft can detect libssh2 inside container images by scanning file contents rather than package metadata. These tools are the most practical option for environments with large container fleets.
Is CVE-2026-55200 a repeat of CVE-2019-3855?
Effectively, yes. Both vulnerabilities are integer overflow flaws in the same ssh2_transport_read() function in transport. c. Both involve an attacker-controlled packet_length value with no upper bound check. Both allow a malicious SSH server to execute code on a connecting client before authentication. The 2019 fix added a LIBSSH2_PACKET_MAXPAYLOAD upper bound check but applied it only to one code path. The full-packet decryption branch – the path CVE-2026-55200 exploits – never received that same guard. Seven years passed before anyone noticed.
CVE-2026-55200 is a pre-authentication RCE in libssh2's ssh2_transport_read() affecting all versions through 1.11. 1. The attack requires no credentials and no user interaction - only a connection to a malicious or compromised SSH server.
The blast radius extends far beyond the libssh2 package itself. Curl, Git, PHP, backup agents, and IoT firmware all carry embedded copies that OS-level patches will not touch.
A public proof of concept exists but demonstrates a local harness, not a turnkey remote exploit. Real-world exploitation requires additional work against specific target binaries, but the PoC meaningfully shortens the development timeline for anyone motivated to build one.
This is a regression of CVE-2019-3855 from 2019: the same function, the same class of bug, and a different code path that was never protected by the 2019 fix.
No official tagged release contains the fix yet. Commit 97acf3d in the mainline branch is the patch. Individual distributions are backporting it. Track your specific vendor's advisory channel.
Apply all three CVEs from this batch together: CVE-2026-55200 (commit 97acf3d), CVE-2026-55199 (commit 1762685), and CVE-2025-15661.
Official References
Author Bio:
Radia is a cybersecurity analyst and technical writer, based in USA. She covers data breaches, threat actor activity, ransomware campaigns, and vulnerability disclosures. She writes for security professionals and everyday readers who want to understand the real mechanics behind the headlines.
Was this article helpful?
React to this post and see the live totals.
Share this :