CVE-2026-116773
russh's SSH client is susceptible to unbounded allocations via EXT_INFO packets
russh is a Rust SSH client and server library that includes an SSH agent protocol implementation. Prior to 0.65.0, the client Session::process_packet path in russh/src/client/encrypted.rs accepts repeated packets encoded with russh's private msg::EXT_INFO = 7 before authentication, while the standards-compliant EXT_INFO message number 82 does not reach the affected handler. The handle_ext_info function appends every parsed extension name to received_extensions without clearing, deduplicating, or bounding the vector. A malicious SSH server that deliberately sends private message number 7 can therefore retain an unbounded number of attacker-controlled extension names for the session lifetime, causing progressive client memory exhaustion. This issue is fixed in version 0.65.0.
Attack profile
How easy it is to exploit
- Attack vector
- Network
- Complexity
- Low
- Privileges needed
- None
- User interaction
- Required
What an attacker can affect
- Confidentiality
- None
- Integrity
- None
- Availability
- Low
Exploit likelihood
What each source reports
CVE List Score used
4.3
russh's SSH client is susceptible to unbounded allocations via EXT_INFO packets
russh is a Rust SSH client and server library that includes an SSH agent protocol implementation. Prior to 0.65.0, the client Session::process_packet path in russh/src/client/encrypted.rs accepts repeated packets encoded with russh's private msg::EXT_INFO = 7 before authentication, while the standards-compliant EXT_INFO message number 82 does not reach the affected handler. The handle_ext_info function appends every parsed extension name to received_extensions without clearing, deduplicating, or bounding the vector. A malicious SSH server that deliberately sends private message number 7 can therefore retain an unbounded number of attacker-controlled extension names for the session lifetime, causing progressive client memory exhaustion. This issue is fixed in version 0.65.0.
- Record
CVE-2026-116773- CVSS 3.1
- 4.3 Medium
CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:N/I:N/A:L - Weakness
- CWE-770
- Updated
- 2026-11-02
EUVDEUVD-2026-111388
4.3
russh is a Rust SSH client and server library that includes an SSH agent protocol implementation. Prior to 0.65.0, the client Session::process_packet path in russh/src/client/encrypted.rs accepts repeated packets encoded with russh's private msg::EXT_INFO = 7 before authentication, while the standards-compliant EXT_INFO message number 82 does not reach the affected handler. The handle_ext_info function appends every parsed extension name to received_extensions without clearing, deduplicating, or bounding the vector. A malicious SSH server that deliberately sends private message number 7 can therefore retain an unbounded number of attacker-controlled extension names for the session lifetime, causing progressive client memory exhaustion. This issue is fixed in version 0.65.0.
- Record
EUVD-2026-111388- CVSS 3.1
- 4.3 Medium
CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:N/I:N/A:L - Updated
- 2026-11-02
GitHub AdvisoriesGHSA-4p9f-7p9m-5vfg
4.3
russh's SSH client is susceptible to unbounded allocations via EXT_INFO packets
Summary
All evidence, reproduction steps, and scripts in the report were verified against a real running instance. Nothing is fabricated or synthetic; every verdict is backed by captured output from an actual deployment. Concretely, the evidence comes from executing the real russh v0.64.1 client packet parser (Session::process_packet handling handle_ext_info) in a live client session with attacker-supplied packet bodies in the pre-authentication state; the captured output below is from that real execution.
russh's client stores every extension name it parses out of an EXT_INFO packet into a per-session vector and never clears, caps, or deduplicates it (russh/src/client/encrypted.rs:433, field declared at russh/src/session.rs:60). The packet is accepted without limit in the pre-authentication states, so a server - which is exactly the attacker position for a client library, and remains one even after the client has verified its host key - can send an unbounded sequence of these packets and grow the client's memory for as long as the session lives: 400 packets of about 26 KB each, carrying 3000 extension names apiece, retained 49.1 MiB (about 4.8 times the wire bytes) with the vector reaching 1,200,000 entries, while an equal volume of banner packets retained nothing. Two details make this reachable in practice: russh accepts EXT_INFO in its pre-auth states with no budget of any kind (its automatic rekey read-limit only engages after authentication), and russh encodes EXT_INFO as its own private message number 7 rather than the 8308 value 82, so the check that might interoperate with a well-behaved peer is inoperative - the malicious server simply speaks number 7. The same growth pattern has been accepted by the project before for other pre-auth allocation sinks; this one is a cross-packet accumulator rather than a single-packet allocation, and none of the published advisories covers it.
Details
The handler appends every parsed extension name to the session state with no bound:
russh/src/client/encrypted.rs:433 (v0.64.1 = main = e5d80a07dc554480b6ea3b2e14adfc190407b627)
enc.received_extensions.push(name.clone()); // no cap, no dedup
russh/src/session.rs:60
pub received_extensions: Vec<String>, // lives for the whole session
The state machine routes EXT_INFO to this handler in both the WaitingAuthServiceRequest and WaitingAuthRequest states (encrypted.rs:111, encrypted.rs:401), i.e. before the user has authenticated, and the read-limit based automatic rekey that would otherwise throttle a flood is only allowed in the authenticated state, so no counter or budget applies pre-auth. The message number involved is russh's private constant msg::EXT_INFO = 7 (russh/src/msg.rs:32, in place since 2022), while RFC 8308 assigns EXT_INFO the value 82: russh does advertise the ext-info capability in its key exchange initiation, so a standards-compliant peer would send the packet as message number 82 - which this parser does not process - but nothing prevents a hostile or compromised server from sending message number 7 directly, and the client parses it unconditionally. Each accepted entry costs several times its wire size once heap and string overhead are counted, and the vector is only ever read (an extension lookup by the awaiter layer), never trimmed. The affected code is identical on the latest tag v0.64.1 and on main (same commit e5d80a07dc554480b6ea3b2e14adfc190407b627), and the accumulation has existed since 2022, so all released client versions are affected.
Proof of concept
The harness constructs a real client Session in the WaitingAuthRequest pre-auth state (the configuration a client holds while the server is asking for authentication), then feeds attacker-controlled packet bodies to the genuine Session::process_packet dispatch - the same function the network event loop calls - so the retention happens in the production parsing path, not a…
- Record
GHSA-4p9f-7p9m-5vfg- CVSS 3.1
- 4.3 Medium
CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:N/I:N/A:L - Weakness
- CWE-770
- Updated
- 2026-11-02
NVD
4.3
russh is a Rust SSH client and server library that includes an SSH agent protocol implementation. Prior to 0.65.0, the client Session::process_packet path in russh/src/client/encrypted.rs accepts repeated packets encoded with russh's private msg::EXT_INFO = 7 before authentication, while the standards-compliant EXT_INFO message number 82 does not reach the affected handler. The handle_ext_info function appends every parsed extension name to received_extensions without clearing, deduplicating, or bounding the vector. A malicious SSH server that deliberately sends private message number 7 can therefore retain an unbounded number of attacker-controlled extension names for the session lifetime, causing progressive client memory exhaustion. This issue is fixed in version 0.65.0.
- Record
CVE-2026-116773- CVSS 3.1
- 4.3 Medium
CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:N/I:N/A:L - Weakness
- CWE-770
- Updated
- 2026-11-02
OSV
4.3
russh's SSH client is susceptible to unbounded allocations via EXT_INFO packets
russh is a Rust SSH client and server library that includes an SSH agent protocol implementation. Prior to 0.65.0, the client Session::process_packet path in russh/src/client/encrypted.rs accepts repeated packets encoded with russh's private msg::EXT_INFO = 7 before authentication, while the standards-compliant EXT_INFO message number 82 does not reach the affected handler. The handle_ext_info function appends every parsed extension name to received_extensions without clearing, deduplicating, or bounding the vector. A malicious SSH server that deliberately sends private message number 7 can therefore retain an unbounded number of attacker-controlled extension names for the session lifetime, causing progressive client memory exhaustion. This issue is fixed in version 0.65.0.
- Record
CVE-2026-116773- CVSS 3.1
- 4.3 Medium
CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:N/I:N/A:L - Weakness
- CWE-770
- Updated
- 2026-11-02
OSVDEBIAN-CVE-2026-116773
4.3
russh is a Rust SSH client and server library that includes an SSH agent protocol implementation. Prior to 0.65.0, the client Session::process_packet path in russh/src/client/encrypted.rs accepts repeated packets encoded with russh's private msg::EXT_INFO = 7 before authentication, while the standards-compliant EXT_INFO message number 82 does not reach the affected handler. The handle_ext_info function appends every parsed extension name to received_extensions without clearing, deduplicating, or bounding the vector. A malicious SSH server that deliberately sends private message number 7 can therefore retain an unbounded number of attacker-controlled extension names for the session lifetime, causing progressive client memory exhaustion. This issue is fixed in version 0.65.0.
- Record
DEBIAN-CVE-2026-116773- CVSS 3.1
- 4.3 Medium
CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:N/I:N/A:L - Updated
- 2026-11-02
OSVGHSA-4p9f-7p9m-5vfg
4.3
russh's SSH client is susceptible to unbounded allocations via EXT_INFO packets
Summary
All evidence, reproduction steps, and scripts in the report were verified against a real running instance. Nothing is fabricated or synthetic; every verdict is backed by captured output from an actual deployment. Concretely, the evidence comes from executing the real russh v0.64.1 client packet parser (Session::process_packet handling handle_ext_info) in a live client session with attacker-supplied packet bodies in the pre-authentication state; the captured output below is from that real execution.
russh's client stores every extension name it parses out of an EXT_INFO packet into a per-session vector and never clears, caps, or deduplicates it (russh/src/client/encrypted.rs:433, field declared at russh/src/session.rs:60). The packet is accepted without limit in the pre-authentication states, so a server - which is exactly the attacker position for a client library, and remains one even after the client has verified its host key - can send an unbounded sequence of these packets and grow the client's memory for as long as the session lives: 400 packets of about 26 KB each, carrying 3000 extension names apiece, retained 49.1 MiB (about 4.8 times the wire bytes) with the vector reaching 1,200,000 entries, while an equal volume of banner packets retained nothing. Two details make this reachable in practice: russh accepts EXT_INFO in its pre-auth states with no budget of any kind (its automatic rekey read-limit only engages after authentication), and russh encodes EXT_INFO as its own private message number 7 rather than the 8308 value 82, so the check that might interoperate with a well-behaved peer is inoperative - the malicious server simply speaks number 7. The same growth pattern has been accepted by the project before for other pre-auth allocation sinks; this one is a cross-packet accumulator rather than a single-packet allocation, and none of the published advisories covers it.
Details
The handler appends every parsed extension name to the session state with no bound:
russh/src/client/encrypted.rs:433 (v0.64.1 = main = e5d80a07dc554480b6ea3b2e14adfc190407b627)
enc.received_extensions.push(name.clone()); // no cap, no dedup
russh/src/session.rs:60
pub received_extensions: Vec<String>, // lives for the whole session
The state machine routes EXT_INFO to this handler in both the WaitingAuthServiceRequest and WaitingAuthRequest states (encrypted.rs:111, encrypted.rs:401), i.e. before the user has authenticated, and the read-limit based automatic rekey that would otherwise throttle a flood is only allowed in the authenticated state, so no counter or budget applies pre-auth. The message number involved is russh's private constant msg::EXT_INFO = 7 (russh/src/msg.rs:32, in place since 2022), while RFC 8308 assigns EXT_INFO the value 82: russh does advertise the ext-info capability in its key exchange initiation, so a standards-compliant peer would send the packet as message number 82 - which this parser does not process - but nothing prevents a hostile or compromised server from sending message number 7 directly, and the client parses it unconditionally. Each accepted entry costs several times its wire size once heap and string overhead are counted, and the vector is only ever read (an extension lookup by the awaiter layer), never trimmed. The affected code is identical on the latest tag v0.64.1 and on main (same commit e5d80a07dc554480b6ea3b2e14adfc190407b627), and the accumulation has existed since 2022, so all released client versions are affected.
Proof of concept
The harness constructs a real client Session in the WaitingAuthRequest pre-auth state (the configuration a client holds while the server is asking for authentication), then feeds attacker-controlled packet bodies to the genuine Session::process_packet dispatch - the same function the network event loop calls - so the retention happens in the production parsing path, not a…
- Record
GHSA-4p9f-7p9m-5vfg- CVSS 3.1
- 4.3 Medium
CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:N/I:N/A:L - Weakness
- CWE-770
- Updated
- 2026-11-02
OSVUBUNTU-CVE-2026-116773
4.3
russh is a Rust SSH client and server library that includes an SSH agent protocol implementation. Prior to 0.65.0, the client Session::process_packet path in russh/src/client/encrypted.rs accepts repeated packets encoded with russh's private msg::EXT_INFO = 7 before authentication, while the standards-compliant EXT_INFO message number 82 does not reach the affected handler. The handle_ext_info function appends every parsed extension name to received_extensions without clearing, deduplicating, or bounding the vector. A malicious SSH server that deliberately sends private message number 7 can therefore retain an unbounded number of attacker-controlled extension names for the session lifetime, causing progressive client memory exhaustion. This issue is fixed in version 0.65.0.
- Record
UBUNTU-CVE-2026-116773- CVSS 3.1
- 4.3 Medium
CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:N/I:N/A:L - Updated
- 2026-11-02
Affected products
Affected packages
| Package | Affected | Fixed |
|---|---|---|
russhcrates.io |
before 0.65 | 0.65 |
rust-russhDebian:14 |
All versions, plus listed versions 0.57.1-10.57.1-20.64.1-10.64.1-2 |
None known |
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-116773 is a medium vulnerability (CVSS 4.3) in Eugeny Russh, published October 27, 2026. No source lists public exploit code. EPSS puts the chance of exploitation in the next 30 days at 0.26%, the 17th percentile. Fixed in russh 0.65.
References
github.com/Eugeny/russh/security/advisories/GHSA-4p9f-7p9m-5vfg
github.com/Eugeny/russh/commit/b33e93beec393e6d29eee69c1b8831736724ee75
github.com/Eugeny/russh/releases/tag/v0.65.0
nvd.nist.gov/vuln/detail/CVE-2026-116773
github.com/advisories/GHSA-4p9f-7p9m-5vfg
github.com/CVEProject/cvelistV5/tree/main/cves/2026/116xxx/CVE-2026-116773.json
Left out here: the rest of 2 source descriptions. The JSON record has them.