CVE-2026-102825: Russh: Configured server auth-attempt cap is not enforced in the USERAUTH_REQUEST runtime path
Details
Affected versions and vulnerable location
- Confirmed present on default branch main at HEAD 0089c89c94753bebbec12b956c07a1cd38740379. - Crate version at HEAD: 0.62.4. - Vulnerable locations on current default branch: - russh/src/server/mod.rs:91 (pub maxauthattempts: usize) - russh/src/server/mod.rs:121 (default maxauthattempts: 10) - russh/src/server/encrypted.rs:89 (USERAUTHREQUEST dispatch into auth handler path) - russh/src/server/encrypted.rs:98 (self.common.authattempts += 1) - russh/src/server/encrypted.rs:53 (only runtime read of authattempts, used for initial reject timing, not attempt limiting) - Default-branch history check did not show a newer merged commit adding enforcement against config.maxauthattempts.
Reachability trace verified
1. Entry point: exported server API server::runstream in russh/src/server/mod.rs:1049. 2. Session run loop in russh/src/server/session.rs processes incoming packets and calls reply(...) (server/session.rs:725). 3. reply forwards encrypted packets to session.serverreadencrypted(...) (server/mod.rs:1221). 4. serverreadencrypted routes USERAUTHREQUEST to enc.serverreadauthrequest(...) (server/encrypted.rs:89). 5. On each request, self.common.authattempts += 1 executes (server/encrypted.rs:98). 6. No comparison against self.common.config.maxauthattempts is present in this runtime flow.
PoC
Reproduction steps and observed output
I did not run a full server process in this environment because Rust tooling is unavailable. I verified the issue from source and command output on the audited tree.
1. Show where maxauthattempts appears:
bash rtk rg -n "maxauthattempts" .scratch/russh/russh/src/server/mod.rs .scratch/russh/russh/src/server/encrypted.rs .scratch/russh/russh/src/server/session.rs
Observed:
text .scratch/russh/russh/src/server/mod.rs:91: pub maxauthattempts: usize, .scratch/russh/russh/src/server/mod.rs:121: maxauthattempts: 10, .scratch/russh/russh/src/server/mod.rs:148: .field("maxauthattempts", &self.maxauthattempts)
2. Show runtime auth-attempt handling:
bash rtk rg -n "authattempts == 0|authattempts \\+= 1" .scratch/russh/russh/src/server/encrypted.rs
Observed:
text 53: let initialnonerejectionwaituntil = if self.common.authattempts == 0 { 98: self.common.authattempts += 1;
3. Show production entrypoint-to-auth path references:
bash rtk rg -n "pub async fn runstream|match reply\\(|serverreadencrypted\\(|serverreadauthrequest\\(" .scratch/russh/russh/src/server/mod.rs .scratch/russh/russh/src/server/session.rs .scratch/russh/russh/src/server/encrypted.rs
Observed:
text .scratch/russh/russh/src/server/encrypted.rs:89: enc.serverreadauthrequest( .scratch/russh/russh/src/server/session.rs:725: match reply(&mut self, &mut handler, &mut pkt).await { .scratch/russh/russh/src/server/mod.rs:1049:pub async fn runstream<H, R>( .scratch/russh/russh/src/server/mod.rs:1221: session.serverreadencrypted(handler, pkt).await
4. Toolchain check:
bash cargo --version
Observed:
text /bin/bash: line 1: cargo: command not found
Impact
Attacker model
- Attacker: unauthenticated remote client with TCP reachability to a russh-backed SSH service. - Preconditions: deployer expects server::Config.maxauthattempts to cap attempts. - Impact: repeated USERAUTHREQUEST attempts continue for a single connection beyond configured limit, increasing online guessing opportunity and backend auth workload.
Suggested fix
Enforce maxauthattempts in the USERAUTHREQUEST branch before invoking auth-method handlers, and fail closed once threshold is reached.
Concrete patch direction in russh/src/server/encrypted.rs:
rust if self.common.config.maxauthattempts > 0 && self.common.authattempts >= self.common.config.maxauthattempts { self.common.disconnect( Disconnect::NoMoreAuthMethodsAvailable, "Too many authentication attempts", "", )?; return Ok(()); }
How it was found and a note on tooling
The researcher synthesized three lens outputs, then revalidated each claim against current main: source presence and commit history, advisory overlap checks in both GitHub advisories and OSV, entrypoint-to-sink reachability, attacker-model realism, and execution-claim integrity. The researcher used gh, git, rg, and direct source inspection under .scratch/russh. Because Rust tooling is unavailable in this worker, this report is intentionally marked source-only.
AI assistance was used while investigating this and while drafting this report. The finding was verified by reading the cited code at HEAD. The vulnerability was not executed it, and that limit is stated plainly above rather than left implied.
Credits: arpitjain099.
Other sources
Russh is a Rust SSH client and server library. Prior to 0.62.6, the USERAUTHREQUEST path reached from server::runstream in russh/src/server/encrypted.rs increments self.common.authattempts but never compares it with server::Config.maxauthattempts. An unauthenticated remote client can continue submitting authentication requests on one connection beyond the configured cap, bypassing the deployment's attempt-limiting policy and increasing online guessing opportunity and backend authentication workload. This issue is fixed in version 0.62.6.
— MITRE
Affected Software
Remediation
Recommended actions to resolve this vulnerability, in priority order.
- Upgrade
Upgrade
rust/russhto a version that resolves this vulnerability.Fixed in 0.62.6 - Upgrade
Upgrade
russhto a version that resolves this vulnerability.Fixed in 0.62.6
Event History
Frequently Asked Questions
Which deployments are exposed to this issue?
Deployments using Russh as an SSH server are exposed if they run a version prior to 0.62.6 and rely on Config.max_auth_attempts to limit authentication requests. The affected path is reached through server::run_stream.
What does an attacker need to exploit it?
An unauthenticated remote client only needs to be able to connect to the SSH server and submit USERAUTH_REQUEST messages on a single connection. No prior credentials or user interaction are required.
Does this affect the configured authentication-attempt limit?
Yes. Although the runtime path increments the authentication-attempt counter, it does not compare that counter with Config.max_auth_attempts, so the configured cap is not enforced for USERAUTH_REQUEST handling.
How can the issue be remediated?
Update Russh to version 0.62.6, which fixes enforcement of the authentication-attempt cap in the affected path.