GHSA-5xvq-cp9x-6p6r: Russh: Pre-auth remote panic via all-zero Curve25519 peer public value (encode_mpint OOB)
A pre-authentication denial-of-service panic in russh 0.62.2 (commit
c4be19f1915c8682f4615c3fd50008512b474491, current default branch main as
of 2026-07-22). An unauthenticated client sends a single SSH_MSG_KEX_ECDH_INIT
whose Q_C is 32 zero bytes. russh's Curve25519 KEX does not reject the
all-zero peer public value, so server_dh() computes the all-zero shared
secret and compute_exchange_hash() then calls encode_mpint(&shared.0, ...),
which indexes s[i] at i == s.len() and panics (`index out of bounds:
the len is 32 but the index is 32`) before host-key signature verification.
The server KEX task dies on the first KEX message, before authentication.
This is reachable with the default server configuration
(Config::default() → Preferred::DEFAULT, whose kex list includes
curve25519-sha256) and requires no caller-supplied parameter. It is
reproduced end-to-end against the unmodified real russh 0.62.2 library (a real
server + raw TCP client over TCP); the PoC below links the real crate, not a
copied snippet. The defect is still present on main HEAD (v0.62.3,
2026-07-22) and is not covered by any of the 11 published russh GHSA advisories
(GHSA-cqvm-j2r2-hwpg / CVE-2023-28113 is modp DH group validation, not
Curve25519).
Rust bounds-checked panics abort the task safely (no memory corruption / RCE);
the impact is remote denial of service.
Details
russh/src/kex/curve25519.rs, server_dh() (server path; attacker = client):
fn server_dh(&mut self, exchange: &mut Exchange, payload: &[u8]) -> Result<(), crate::Error> {
// only the 32-byte length is checked, NOT zero / low-order:
let mut pubkey = MontgomeryPoint([0; 32]);
pubkey.0.clone_from_slice(&payload[5..5 + 32]); // line 73
...
let shared = server_secret * client_pubkey; // all-zero when client_pubkey == [0;32]
self.shared_secret = Some(shared); // line 86
Ok(())
}
The server then computes the exchange hash before verifying the host-key
signature (russh/src/server/kex.rs):
kex.server_dh(exchange, &input.buffer)?; //
Details
Original advisory: https://github.com/advisories/GHSA-5xvq-cp9x-6p6r
More from GitHub Security Advisories
- mediumGHSA-jr6p-8pjj-mfx6: Capsule has an incomplete fix of CVE-2026-22872: TenantResource RawItems and Generators s…2026-07-31
- mediumGHSA-68cj-mvg9-rgm2: Capsule: CapsuleConfiguration NodeMetadata regex fields lack webhook validation, allowing…2026-07-31
- mediumGHSA-ff84-5f28-78qj: re2: Out-of-bounds heap read in `exec`/`test`/`match` via attacker-influenced `lastIndex`…2026-07-31
- mediumGHSA-6hxr-mr5r-9836: re2: Global `String.prototype.match` with an empty-matchable pattern never advances → inf…2026-07-31
- mediumGHSA-x83g-979r-f5fh: Sylius Mollie Plugin has unauthenticated IDOR that leaks order token and customer PII2026-07-31