CVE-2026-73429
Russh: client wrong-length X25519 `clone_from_slice` panic (pre-auth DoS)
Russh is a Rust SSH client & server library. Prior to 0.62.4, a malicious SSH server can crash a russh client session with a malformed KEX_ECDH_REPLY containing a server ephemeral value that is not 32 bytes long. The client-side Curve25519Kex::compute_shared_secret function in russh/src/kex/curve25519.rs passes the decoded exchange.server_ephemeral value to clone_from_slice without validating its length, causing a deterministic panic before the server host key is verified. The panic terminates the spawned client session task and surfaces as a JoinError, while the embedding process normally remains running. This issue is fixed in version 0.62.4.
Attack profile
How easy it is to exploit
- Attack vector
- Network
- Complexity
- Low
- Privileges needed
- None
- User interaction
- None
What an attacker can affect
- Confidentiality
- None
- Integrity
- None
- Availability
- Low
Exploit likelihood
What each source reports
CVE List Score used
5.3
Russh: client wrong-length X25519 `clone_from_slice` panic (pre-auth DoS)
Russh is a Rust SSH client & server library. Prior to 0.62.4, a malicious SSH server can crash a russh client session with a malformed KEX_ECDH_REPLY containing a server ephemeral value that is not 32 bytes long. The client-side Curve25519Kex::compute_shared_secret function in russh/src/kex/curve25519.rs passes the decoded exchange.server_ephemeral value to clone_from_slice without validating its length, causing a deterministic panic before the server host key is verified. The panic terminates the spawned client session task and surfaces as a JoinError, while the embedding process normally remains running. This issue is fixed in version 0.62.4.
- Record
CVE-2026-73429- CVSS 3.1
- 5.3 Medium
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:L - Weakness
- CWE-704, CWE-754
- Updated
- 2026-11-02
EUVDEUVD-2026-57624
5.3
Russh is a Rust SSH client & server library. Prior to 0.62.4, a malicious SSH server can crash a russh client session with a malformed KEX_ECDH_REPLY containing a server ephemeral value that is not 32 bytes long. The client-side Curve25519Kex::compute_shared_secret function in russh/src/kex/curve25519.rs passes the decoded exchange.server_ephemeral value to clone_from_slice without validating its length, causing a deterministic panic before the server host key is verified. The panic terminates the spawned client session task and surfaces as a JoinError, while the embedding process normally remains running. This issue is fixed in version 0.62.4.
- Record
EUVD-2026-57624- CVSS 3.1
- 5.3 Medium
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:L - Updated
- 2026-11-02
GitHub AdvisoriesGHSA-g9hv-x236-4qp3
5.3
Russh: client wrong-length X25519 `clone_from_slice` panic (pre-auth DoS)
Summary
A malicious SSH server can crash a russh client session with a single
malformed key-exchange reply, causing a pre-authentication Denial-of-Service
before the server host key is verified. The embedding process itself stays
up, but the connection is killed deterministically.
Details
Every other kex path in russh validates the peer ephemeral length before
cloning:
Curve25519Kex::server_dh(russh/src/kex/curve25519.rs:61-65) checksif pubkey_len != 32 { return Err(crate::Error::Kex); }beforeclone_from_slice.- The hybrid ML-KEM, ECDH-NIST, and DH/GEX paths all validate lengths.
Only the client-side curve25519 compute_shared_secret is missing the check.
This asymmetric validation gap makes the bug easy to miss in code review: a
malicious client cannot panic a russh server this way (the server path
checks the length), but a malicious server can panic a russh client.
Incriminated source code (repo-relative paths):
- Vulnerable
compute_shared_secret:russh/src/kex/curve25519.rs:110-117(panic at line 113) - Client-side entry point:
russh/src/client/kex.rs:266-277(KEX_ECDH_REPLY→Bytes::decode→compute_shared_secret) - Server-side contrast (has the length check):
russh/src/kex/curve25519.rs:51-88(server_dh) - Session spawn site:
russh/src/client/mod.rs(connect_stream→russh_util::runtime::spawn) - Runtime wrapper:
russh-util/src/runtime.rs:37-48(spawnwrapstokio::spawn; panic surfaces asJoinError)
PoC
A standalone, self-contained Cargo PoC is provided in
vuln_poc/vuln_002_client_wronglen_x25519_panic/ in this repo. It installs a
global panic hook that sets an AtomicBool if any panic fires, starts a
malicious raw SSH server on 127.0.0.1:0 that completes the SSH id and
KEXINIT exchange, reads the client KEX_ECDH_INIT, and sends
KEX_ECDH_REPLY with a 16-byte server ephemeral (instead of 32) and a fake
signature. It then calls russh::client::connect with Preferred::kex set
to curve25519-sha256 and a handler that accepts any server key (the check
is never reached because the client panics first) and prints a clear verdict.
Build & run:
cd vuln_poc/vuln_002_client_wronglen_x25519_panic
cargo run --release
Expected output (verdict line, from a successful reproduction):
[poc] panic captured: panicked at russh/src/kex/curve25519.rs:113:25:
copy_from_slice: source slice length (16) does not match destination slice length (32)
[!] Vulnerability reproduced: russh client panicked in Curve25519Kex::compute_shared_secret
on a wrong-length (16-byte) server ephemeral before verifying the host key signature
(pre-auth client DoS).
The malicious payload is the f field of KEX_ECDH_REPLY:
MSG_KEX_ECDH_REPLY (1 byte, value 0x1f)
string K_S (server host key blob — any valid-looking bytes)
string f (server ephemeral — 16 bytes of 0x00 instead of 32)
string signature (fake; never verified by the client)
The length prefix of f is 4 (u32 BE) = 16, followed by 16 bytes. The
russh client decodes this into exchange.server_ephemeral (a Vec<u8> of
length 16) and passes it to compute_shared_secret, which panics on
clone_from_slice.
Impact
What kind of vulnerability: CWE-704 (incorrect type conversion / cast —
clone_from_slice length mismatch) → deterministic panic → pre-authentication
per-connection Denial-of-Service. The attacker does not need the server's
private key; any network position that can deliver a malformed
KEX_ECDH_REPLY (a rogue server, or a MitM before authentication) suffices.
Who is impacted: any deployment that uses russh::client::connect (or
connect_stream) to connect to an attacker-controlled or MitM-reachable SSH
server, and that negotiates curve25519-sha256 (the default and
most-preferred kex algorithm in russh). A single malformed
KEX_ECDH_REPLY kills the client session; the attack is…
- Record
GHSA-g9hv-x236-4qp3- CVSS 3.1
- 5.3 Medium
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:L - Weakness
- CWE-704, CWE-754
- Updated
- 2026-11-02
NVD
5.3
Russh is a Rust SSH client & server library. Prior to 0.62.4, a malicious SSH server can crash a russh client session with a malformed KEX_ECDH_REPLY containing a server ephemeral value that is not 32 bytes long. The client-side Curve25519Kex::compute_shared_secret function in russh/src/kex/curve25519.rs passes the decoded exchange.server_ephemeral value to clone_from_slice without validating its length, causing a deterministic panic before the server host key is verified. The panic terminates the spawned client session task and surfaces as a JoinError, while the embedding process normally remains running. This issue is fixed in version 0.62.4.
- Record
CVE-2026-73429- CVSS 3.1
- 5.3 Medium
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:L - Weakness
- CWE-704, CWE-754
- Updated
- 2026-11-02
OSV
5.3
Russh: client wrong-length X25519 `clone_from_slice` panic (pre-auth DoS)
Russh is a Rust SSH client & server library. Prior to 0.62.4, a malicious SSH server can crash a russh client session with a malformed KEX_ECDH_REPLY containing a server ephemeral value that is not 32 bytes long. The client-side Curve25519Kex::compute_shared_secret function in russh/src/kex/curve25519.rs passes the decoded exchange.server_ephemeral value to clone_from_slice without validating its length, causing a deterministic panic before the server host key is verified. The panic terminates the spawned client session task and surfaces as a JoinError, while the embedding process normally remains running. This issue is fixed in version 0.62.4.
- Record
CVE-2026-73429- CVSS 3.1
- 5.3 Medium
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:L - Weakness
- CWE-704, CWE-754
- Updated
- 2026-11-02
OSVDEBIAN-CVE-2026-73429
5.3
Russh is a Rust SSH client & server library. Prior to 0.62.4, a malicious SSH server can crash a russh client session with a malformed KEX_ECDH_REPLY containing a server ephemeral value that is not 32 bytes long. The client-side Curve25519Kex::compute_shared_secret function in russh/src/kex/curve25519.rs passes the decoded exchange.server_ephemeral value to clone_from_slice without validating its length, causing a deterministic panic before the server host key is verified. The panic terminates the spawned client session task and surfaces as a JoinError, while the embedding process normally remains running. This issue is fixed in version 0.62.4.
- Record
DEBIAN-CVE-2026-73429- CVSS 3.1
- 5.3 Medium
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:L - Updated
- 2026-11-02
OSVGHSA-g9hv-x236-4qp3
5.3
Russh: client wrong-length X25519 `clone_from_slice` panic (pre-auth DoS)
Summary
A malicious SSH server can crash a russh client session with a single
malformed key-exchange reply, causing a pre-authentication Denial-of-Service
before the server host key is verified. The embedding process itself stays
up, but the connection is killed deterministically.
Details
Every other kex path in russh validates the peer ephemeral length before
cloning:
Curve25519Kex::server_dh(russh/src/kex/curve25519.rs:61-65) checksif pubkey_len != 32 { return Err(crate::Error::Kex); }beforeclone_from_slice.- The hybrid ML-KEM, ECDH-NIST, and DH/GEX paths all validate lengths.
Only the client-side curve25519 compute_shared_secret is missing the check.
This asymmetric validation gap makes the bug easy to miss in code review: a
malicious client cannot panic a russh server this way (the server path
checks the length), but a malicious server can panic a russh client.
Incriminated source code (repo-relative paths):
- Vulnerable
compute_shared_secret:russh/src/kex/curve25519.rs:110-117(panic at line 113) - Client-side entry point:
russh/src/client/kex.rs:266-277(KEX_ECDH_REPLY→Bytes::decode→compute_shared_secret) - Server-side contrast (has the length check):
russh/src/kex/curve25519.rs:51-88(server_dh) - Session spawn site:
russh/src/client/mod.rs(connect_stream→russh_util::runtime::spawn) - Runtime wrapper:
russh-util/src/runtime.rs:37-48(spawnwrapstokio::spawn; panic surfaces asJoinError)
PoC
A standalone, self-contained Cargo PoC is provided in
vuln_poc/vuln_002_client_wronglen_x25519_panic/ in this repo. It installs a
global panic hook that sets an AtomicBool if any panic fires, starts a
malicious raw SSH server on 127.0.0.1:0 that completes the SSH id and
KEXINIT exchange, reads the client KEX_ECDH_INIT, and sends
KEX_ECDH_REPLY with a 16-byte server ephemeral (instead of 32) and a fake
signature. It then calls russh::client::connect with Preferred::kex set
to curve25519-sha256 and a handler that accepts any server key (the check
is never reached because the client panics first) and prints a clear verdict.
Build & run:
cd vuln_poc/vuln_002_client_wronglen_x25519_panic
cargo run --release
Expected output (verdict line, from a successful reproduction):
[poc] panic captured: panicked at russh/src/kex/curve25519.rs:113:25:
copy_from_slice: source slice length (16) does not match destination slice length (32)
[!] Vulnerability reproduced: russh client panicked in Curve25519Kex::compute_shared_secret
on a wrong-length (16-byte) server ephemeral before verifying the host key signature
(pre-auth client DoS).
The malicious payload is the f field of KEX_ECDH_REPLY:
MSG_KEX_ECDH_REPLY (1 byte, value 0x1f)
string K_S (server host key blob — any valid-looking bytes)
string f (server ephemeral — 16 bytes of 0x00 instead of 32)
string signature (fake; never verified by the client)
The length prefix of f is 4 (u32 BE) = 16, followed by 16 bytes. The
russh client decodes this into exchange.server_ephemeral (a Vec<u8> of
length 16) and passes it to compute_shared_secret, which panics on
clone_from_slice.
Impact
What kind of vulnerability: CWE-704 (incorrect type conversion / cast —
clone_from_slice length mismatch) → deterministic panic → pre-authentication
per-connection Denial-of-Service. The attacker does not need the server's
private key; any network position that can deliver a malformed
KEX_ECDH_REPLY (a rogue server, or a MitM before authentication) suffices.
Who is impacted: any deployment that uses russh::client::connect (or
connect_stream) to connect to an attacker-controlled or MitM-reachable SSH
server, and that negotiates curve25519-sha256 (the default and
most-preferred kex algorithm in russh). A single malformed
KEX_ECDH_REPLY kills the client session; the attack is…
- Record
GHSA-g9hv-x236-4qp3- CVSS 3.1
- 5.3 Medium
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:L - Weakness
- CWE-704, CWE-754
- Updated
- 2026-11-02
OSVUBUNTU-CVE-2026-73429
5.3
Russh is a Rust SSH client & server library. Prior to 0.62.4, a malicious SSH server can crash a russh client session with a malformed KEX_ECDH_REPLY containing a server ephemeral value that is not 32 bytes long. The client-side Curve25519Kex::compute_shared_secret function in russh/src/kex/curve25519.rs passes the decoded exchange.server_ephemeral value to clone_from_slice without validating its length, causing a deterministic panic before the server host key is verified. The panic terminates the spawned client session task and surfaces as a JoinError, while the embedding process normally remains running. This issue is fixed in version 0.62.4.
- Record
UBUNTU-CVE-2026-73429- CVSS 3.1
- 5.3 Medium
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:L - Updated
- 2026-11-02
Affected products
Affected packages
| Package | Affected | Fixed |
|---|---|---|
russhcrates.io |
through 0.62.3 | 0.62.4 |
rust-russhDebian:14 |
before 0.64.1-1, plus listed versions 0.57.1-10.57.1-2 |
0.64.1-1 |
russhcrates.io |
before 0.62.4 | 0.62.4 |
rust-russhUbuntu:26.10 |
All versions, plus listed versions 0.57.1-2 |
None known |
History
| Recorded | Changed | Sources |
|---|---|---|
| first indexed | CVE List, EUVD, GitHub Advisories, NVD, OSV |
Dates are when Every CVE recorded each change. Upstream dates may differ.
In short
CVE-2026-73429 is a medium vulnerability (CVSS 5.3) in Eugeny Russh, published July 24, 2026. No source lists public exploit code. EPSS puts the chance of exploitation in the next 30 days at 0.51%, the 43rd percentile. Fixed in russh 0.62.4.
References
github.com/Eugeny/russh/security/advisories/GHSA-g9hv-x236-4qp3
github.com/Eugeny/russh/commit/a7fc1eb5717264e31c3c5f7dd849b73989a08f3d
github.com/Eugeny/russh/releases/tag/v0.62.4
github.com/advisories/GHSA-g9hv-x236-4qp3
github.com/CVEProject/cvelistV5/tree/main/cves/2026/73xxx/CVE-2026-73429.json
nvd.nist.gov/vuln/detail/CVE-2026-73429
Left out here: the rest of 2 source descriptions. The JSON record has them.