Every CVE Search/ Get API key

CVE-2026-116773

russh's SSH client is susceptible to unbounded allocations via EXT_INFO packets

4.3 MediumFix available

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

0.26%Unchanged since Oct 28, 2026
90%50%10%1%

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 MediumCVSS: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 MediumCVSS: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 MediumCVSS: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 MediumCVSS: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 MediumCVSS: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 MediumCVSS: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 MediumCVSS: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 MediumCVSS: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

Affected packages
PackageAffectedFixed
russh
crates.io
before 0.65
0.65
rust-russh
Debian:14
All versions, plus listed versions
0.57.1-10.57.1-20.64.1-10.64.1-2
None known
rust-russh
Ubuntu:26.10
All versions, plus listed versions
0.57.1-2
None known

History

History
RecordedChangedSources
first indexedCVE 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

Show 4 moreShow less
This page doesn't list everything

Left out here: the rest of 2 source descriptions. The JSON record has them.

MoveEnter Open