Russh: Unchecked keyboard-interactive prompt count in client auth path
Date: 2026-06
Affected: rust/russh
Attack vector: dos
Category: vulnerability-disclosure
Severity: Medium
CVE: CVE-2026-48107
CWE: CWE-20
CVSS: 6.5 (CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:N/I:N/A:H)

### Summary In the `russh` client keyboard-interactive authentication path, a malicious SSH server could send a `USERAUTH_INFO_REQUEST` with an attacker-controlled prompt count, and the client would use that raw count directly in `Vec::with_capacity(...)` before validating that enough prompt data was actually present in the packet. This is a client-side denial-of-service / resource-exhaustion issue on the keyboard-interactive auth path. ### Details The vulnerable code path is in: - `russh/src/client/encrypted.rs` When the client is in `CurrentRequest::KeyboardInteractive` state and receives `SSH_MSG_USERAUTH_INFO_REQUEST`, it parses: 1. `name` 2. `instructions` 3. `language tag` 4. `n_prompts` Before the fix, the code then did: ```rust let n_prompts = map_err!(u32::decode(&mut r))?; let mut prompts = Vec::with_capacity(n_prompts.try_into().unwrap_or(0)); ``` That means a malicious server could advertise an enormous `n_prompts` value even if the packet contained no prompt bodies at all. The fix rejects inconsistent prompt counts before allocating: ```rust let n_prompts = map_err!(u32::decode(&mut r))?; let max_prompts = r.remaining_len() / 5; let n_prompts = n_prompts as usize; if n_prompts > max_prompts { return Err(crate::Error::Inconsistent.into()); } let mut prompts = Vec::with_capacity(n_prompts); ``` Each prompt needs at least 4 bytes of string length plus 1 byte of echo flag, so `remaining_len() / 5` is a safe upper bound. If the declared count exceeds wh


Mitigations:

Architectural layers (MAESTRO):