CVE-2026-73430 Overview
CVE-2026-73430 is a pre-authentication denial-of-service vulnerability in Russh, a Rust SSH client and server library maintained by Eugeny. Versions prior to 0.62.4 accept a malformed Curve25519 key exchange message that triggers a panic in the server key-exchange task. An unauthenticated remote attacker can send an SSH_MSG_KEX_ECDH_INIT message containing a 32-byte all-zero Q_C value. The server computes an all-zero shared secret, then panics inside encode_mpint when it indexes past the end of the input while skipping leading zero bytes. The issue is classified as [CWE-754: Improper Check for Unusual or Exceptional Conditions] and is fixed in version 0.62.4.
Critical Impact
Any network-reachable Russh-based SSH server can be crashed by a single unauthenticated packet, disrupting availability for all connecting clients.
Affected Products
- Russh SSH library versions prior to 0.62.4
- Rust applications embedding Russh as an SSH server
- Downstream services depending on russh crate for SSH transport
Discovery Timeline
- 2026-08-12 - CVE-2026-73430 published to NVD
- 2026-08-12 - Last updated in NVD database
Technical Details for CVE-2026-73430
Vulnerability Analysis
The defect lies in the Curve25519 key exchange handler Curve25519Kex::server_dh in russh/src/kex/curve25519.rs. The function fails to reject a peer public key composed entirely of zero bytes. Curve25519 scalar multiplication with an all-zero point produces an all-zero shared secret, which is a well-known contributory-behavior edge case that implementations are expected to reject.
After the flawed key agreement completes, compute_exchange_hash invokes encode_mpint in russh/src/kex/mod.rs to serialize the shared secret as an SSH mpint. The encoder loops forward through the byte slice skipping leading zeros. When every byte is zero, the loop advances the index to the slice length, and the subsequent indexing operation panics. The panic terminates the key-exchange task before authentication occurs.
Root Cause
Two defects combine to produce the crash. First, server_dh does not validate the peer public key against the small-subgroup and all-zero cases required by RFC 7748. Second, encode_mpint does not handle the boundary condition where the input reduces to zero significant bytes. Either defect alone would be sufficient to cause the panic under attacker-controlled input.
Attack Vector
Exploitation requires only network reachability to the target SSH port. The attacker opens a TCP connection, completes the SSH version exchange, and sends an SSH_MSG_KEX_ECDH_INIT packet with a 32-byte all-zero Q_C field. No credentials, banner grabbing, or protocol negotiation beyond the initial key exchange step are required. The server-side task panics, and the connection or process is disrupted depending on how the host application handles Tokio task failures.
// Patch: reject all-zero Curve25519 peer public keys
// Source: https://github.com/Eugeny/russh/commit/a7fc1eb5717264e31c3c5f7dd849b73989a08f3d
pubkey
};
+ if client_pubkey.0 == [0u8; 32] {
+ debug!("client sent zero curve25519 pubkey");
+ return Err(crate::Error::Kex);
+ }
+
let server_secret = Scalar::from_bytes_mod_order(rand::random::<[u8; 32]>());
let server_pubkey = (ED25519_BASEPOINT_TABLE * &server_secret).to_montgomery();
// Patch: handle all-zero mpint input in encode_mpint
// Source: https://github.com/Eugeny/russh/commit/a7fc1eb5717264e31c3c5f7dd849b73989a08f3d
while i < s.len() && s[i] == 0 {
i += 1
}
+ if i == s.len() {
+ 0u32.encode(w)?;
+ return Ok(());
+ }
// If the first non-zero is >= 128, write its length (u32, BE), followed by 0.
if s[i] & 0x80 != 0 {
((s.len() - i + 1) as u32).encode(w)?;
Detection Methods for CVE-2026-73430
Indicators of Compromise
- SSH connections that send SSH_MSG_KEX_ECDH_INIT (message type 30) with a 32-byte payload of 0x00
- Application logs recording Tokio task panics originating in russh::kex::curve25519 or russh::kex::encode_mpint
- Abrupt termination of SSH key-exchange sessions before authentication banners are exchanged
Detection Strategies
- Inspect SSH transport traffic for SSH_MSG_KEX_ECDH_INIT packets carrying an all-zero Q_C field and alert on repeat occurrences from the same source.
- Correlate short-lived TCP connections to SSH ports with subsequent panic messages in host application logs.
- Track sudden spikes in failed key-exchange attempts against services known to embed the russh crate.
Monitoring Recommendations
- Enable structured logging for the host process to capture panic backtraces referencing russh/src/kex/.
- Instrument SSH endpoints with connection-rate and error-rate metrics to detect repeated crash-restart cycles.
- Aggregate crash telemetry across fleet instances to identify coordinated exploitation attempts.
How to Mitigate CVE-2026-73430
Immediate Actions Required
- Upgrade the russh dependency to version 0.62.4 or later and rebuild all affected binaries.
- Audit Cargo.lock files across services to confirm no transitive dependency pulls in a vulnerable Russh version.
- Restart any long-running SSH services after upgrading to ensure the patched code path is active.
Patch Information
The vendor released the fix in Russh v0.62.4. The patch commit a7fc1eb5 adds an explicit check that rejects all-zero Curve25519 peer public keys and hardens encode_mpint against fully-zero inputs. Full technical details are available in the GitHub Security Advisory GHSA-5xvq-cp9x-6p6r.
Workarounds
- Restrict inbound access to Russh-based SSH services using firewall rules or allow-lists until the upgrade is deployed.
- Front the service with a hardened SSH proxy or bastion that validates key-exchange messages before forwarding.
- Configure the host application to supervise and restart panicked tasks to reduce sustained outages while patching is scheduled.
# Update the russh crate to a patched version
cargo update -p russh --precise 0.62.4
cargo build --release
# Verify the resolved version
cargo tree -i russh
Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.

