Every CVE Search/ Get API key

CVE-2026-46705

russh server userauth state is not reset when authentication principal changes

5.3 MediumFix available

Russh is a Rust SSH client & server library. From version 0.34.0-beta.1 to before version 0.61.0, the russh server authentication path keeps internal userauth state across SSH_MSG_USERAUTH_REQUEST messages without separating that state when the request principal changes. RFC 4252 allows the user name and service name fields to change between authentication requests. The issue is not that such changes are invalid. The issue is that russh-owned authentication state, such as remaining methods, partial-success state, and in-progress method state, can remain associated with the connection and then influence a later request for a different (user, service). This is an internal library state mismatch. This issue has been patched in version 0.61.0.

Attack profile

How easy it is to exploit

Attack vector
Network
Complexity
Low
Privileges needed
None
User interaction
None

What an attacker can affect

Confidentiality
None
Integrity
Low
Availability
None

Exploit likelihood

0.22%Up 0.2 points since Jun 11, 2026
90%50%10%1%

What each source reports

CVE List Score used 5.3

russh server userauth state is not reset when authentication principal changes

Russh is a Rust SSH client & server library. From version 0.34.0-beta.1 to before version 0.61.0, the russh server authentication path keeps internal userauth state across SSH_MSG_USERAUTH_REQUEST messages without separating that state when the request principal changes. RFC 4252 allows the user name and service name fields to change between authentication requests. The issue is not that such changes are invalid. The issue is that russh-owned authentication state, such as remaining methods, partial-success state, and in-progress method state, can remain associated with the connection and then influence a later request for a different (user, service). This is an internal library state mismatch. This issue has been patched in version 0.61.0.

Record
CVE-2026-46705
CVSS 3.1
5.3 MediumCVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:L/A:N
Weakness
CWE-287
Updated
2026-11-02
EUVDEUVD-2026-36126 5.3

Russh is a Rust SSH client & server library. From version 0.34.0-beta.1 to before version 0.61.0, the russh server authentication path keeps internal userauth state across SSH_MSG_USERAUTH_REQUEST messages without separating that state when the request principal changes. RFC 4252 allows the user name and service name fields to change between authentication requests. The issue is not that such changes are invalid. The issue is that russh-owned authentication state, such as remaining methods, partial-success state, and in-progress method state, can remain associated with the connection and then influence a later request for a different (user, service). This is an internal library state mismatch. This issue has been patched in version 0.61.0.

Record
EUVD-2026-36126
CVSS 3.1
5.3 MediumCVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:L/A:N
Updated
2026-11-02
GitHub AdvisoriesGHSA-hpv4-5h6f-wqr3 5.3

russh server userauth state is not reset when authentication principal changes

Summary

The russh server authentication path keeps internal userauth state across SSH_MSG_USERAUTH_REQUEST messages without separating that state when the request principal changes.

RFC 4252 allows the user name and service name fields to change between authentication requests. The issue is not that such changes are invalid. The issue is that russh-owned authentication state, such as remaining methods, partial-success state, and in-progress method state, can remain associated with the connection and then influence a later request for a different (user, service).

This is an internal library state mismatch. Applications are responsible for any authentication state they keep in their own handlers, but russh must reset or separate state that russh itself owns.

Details

The relevant server-side auth logic is in:

  • russh/src/server/encrypted.rs
  • russh/src/auth.rs

RFC 4252 section 5 says the user name and service name fields are repeated in every SSH_MSG_USERAUTH_REQUEST and may change. It also says the server implementation must check those fields in every message and flush accumulated authentication state if they change; if it cannot flush that state, it must disconnect.

In vulnerable russh code, the username and service are decoded from each SSH_MSG_USERAUTH_REQUEST, while the AuthRequest state remains connection-scoped. That state includes:

  • methods, which is later encoded as the SSH_MSG_USERAUTH_FAILURE remaining-methods list.
  • partial_success, which is later encoded in SSH_MSG_USERAUTH_FAILURE.
  • current, which tracks in-progress method state such as public-key offer or keyboard-interactive challenge state.
  • rejection_count.

If one request narrows russh's internal methods set, a later request for a different user can observe that narrowed set unless the internal state is reset at the principal boundary.

PoC

The PoC demonstrates only russh-owned state. The handler does not store any cross-request state. Alice's request narrows russh's remaining methods to password; Bob's later plain reject should not reuse that internal state.

struct RemainingMethodsUserSwitchServer;

impl server::Handler for RemainingMethodsUserSwitchServer {
    type Error = russh::Error;

    async fn auth_none(&mut self, user: &str) -> Result<server::Auth, Self::Error> {
        if user == "alice" {
            Ok(server::Auth::Reject {
                proceed_with_methods: Some(MethodSet::from(&[MethodKind::Password][..])),
                partial_success: true,
            })
        } else {
            Ok(server::Auth::reject())
        }
    }
}

#[tokio::test]
async fn auth_does_not_carry_remaining_methods_across_username_change() {
    let alice = session.authenticate_none("alice").await.unwrap();

    assert!(matches!(
        alice,
        client::AuthResult::Failure {
            ref remaining_methods,
            ..
        } if *remaining_methods == MethodSet::from(&[MethodKind::Password][..])
    ));

    let bob = session.authenticate_none("bob").await.unwrap();

    if let client::AuthResult::Failure {
        remaining_methods, ..
    } = bob {
        assert!(
            remaining_methods.contains(&MethodKind::PublicKey),
            "server reused Alice's narrowed remaining methods for Bob: {remaining_methods:?}"
        );
    }
}

On upstream/main, this fails with:

server reused Alice's narrowed remaining methods for Bob: MethodSet([Password])

That failure is produced by russh's retained AuthRequest.methods; it does not depend on handler-owned MFA/session state.

Impact

Suggested provisional CVSS v3.1:

  • CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:L/A:N
  • Score: 5.3

Reasoning:

  • AV:N: reachable by a remote SSH client during authentication.
  • AC:L: the attack is a normal sequence of SSH user-auth packets.
  • PR:N: the attacker does not need an already-authenticated SSH session.
  • UI:N: no user interaction is required on the…
Record
GHSA-hpv4-5h6f-wqr3
CVSS 3.1
5.3 MediumCVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:L/A:N
Weakness
CWE-287
Updated
2026-11-02
NVD 5.3

Russh is a Rust SSH client & server library. From version 0.34.0-beta.1 to before version 0.61.0, the russh server authentication path keeps internal userauth state across SSH_MSG_USERAUTH_REQUEST messages without separating that state when the request principal changes. RFC 4252 allows the user name and service name fields to change between authentication requests. The issue is not that such changes are invalid. The issue is that russh-owned authentication state, such as remaining methods, partial-success state, and in-progress method state, can remain associated with the connection and then influence a later request for a different (user, service). This is an internal library state mismatch. This issue has been patched in version 0.61.0.

Record
CVE-2026-46705
CVSS 3.1
5.3 MediumCVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:L/A:N
Weakness
CWE-287
Updated
2026-11-02
OSV 5.3

russh server userauth state is not reset when authentication principal changes

Russh is a Rust SSH client & server library. From version 0.34.0-beta.1 to before version 0.61.0, the russh server authentication path keeps internal userauth state across SSH_MSG_USERAUTH_REQUEST messages without separating that state when the request principal changes. RFC 4252 allows the user name and service name fields to change between authentication requests. The issue is not that such changes are invalid. The issue is that russh-owned authentication state, such as remaining methods, partial-success state, and in-progress method state, can remain associated with the connection and then influence a later request for a different (user, service). This is an internal library state mismatch. This issue has been patched in version 0.61.0.

Record
CVE-2026-46705
CVSS 3.1
5.3 MediumCVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:L/A:N
Weakness
CWE-287
Updated
2026-11-02
OSVDEBIAN-CVE-2026-46705 5.3

Russh is a Rust SSH client & server library. From version 0.34.0-beta.1 to before version 0.61.0, the russh server authentication path keeps internal userauth state across SSH_MSG_USERAUTH_REQUEST messages without separating that state when the request principal changes. RFC 4252 allows the user name and service name fields to change between authentication requests. The issue is not that such changes are invalid. The issue is that russh-owned authentication state, such as remaining methods, partial-success state, and in-progress method state, can remain associated with the connection and then influence a later request for a different (user, service). This is an internal library state mismatch. This issue has been patched in version 0.61.0.

Record
DEBIAN-CVE-2026-46705
CVSS 3.1
5.3 MediumCVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:L/A:N
Updated
2026-11-02
OSVGHSA-hpv4-5h6f-wqr3 5.3

russh server userauth state is not reset when authentication principal changes

Summary

The russh server authentication path keeps internal userauth state across SSH_MSG_USERAUTH_REQUEST messages without separating that state when the request principal changes.

RFC 4252 allows the user name and service name fields to change between authentication requests. The issue is not that such changes are invalid. The issue is that russh-owned authentication state, such as remaining methods, partial-success state, and in-progress method state, can remain associated with the connection and then influence a later request for a different (user, service).

This is an internal library state mismatch. Applications are responsible for any authentication state they keep in their own handlers, but russh must reset or separate state that russh itself owns.

Details

The relevant server-side auth logic is in:

  • russh/src/server/encrypted.rs
  • russh/src/auth.rs

RFC 4252 section 5 says the user name and service name fields are repeated in every SSH_MSG_USERAUTH_REQUEST and may change. It also says the server implementation must check those fields in every message and flush accumulated authentication state if they change; if it cannot flush that state, it must disconnect.

In vulnerable russh code, the username and service are decoded from each SSH_MSG_USERAUTH_REQUEST, while the AuthRequest state remains connection-scoped. That state includes:

  • methods, which is later encoded as the SSH_MSG_USERAUTH_FAILURE remaining-methods list.
  • partial_success, which is later encoded in SSH_MSG_USERAUTH_FAILURE.
  • current, which tracks in-progress method state such as public-key offer or keyboard-interactive challenge state.
  • rejection_count.

If one request narrows russh's internal methods set, a later request for a different user can observe that narrowed set unless the internal state is reset at the principal boundary.

PoC

The PoC demonstrates only russh-owned state. The handler does not store any cross-request state. Alice's request narrows russh's remaining methods to password; Bob's later plain reject should not reuse that internal state.

struct RemainingMethodsUserSwitchServer;

impl server::Handler for RemainingMethodsUserSwitchServer {
    type Error = russh::Error;

    async fn auth_none(&mut self, user: &str) -> Result<server::Auth, Self::Error> {
        if user == "alice" {
            Ok(server::Auth::Reject {
                proceed_with_methods: Some(MethodSet::from(&[MethodKind::Password][..])),
                partial_success: true,
            })
        } else {
            Ok(server::Auth::reject())
        }
    }
}

#[tokio::test]
async fn auth_does_not_carry_remaining_methods_across_username_change() {
    let alice = session.authenticate_none("alice").await.unwrap();

    assert!(matches!(
        alice,
        client::AuthResult::Failure {
            ref remaining_methods,
            ..
        } if *remaining_methods == MethodSet::from(&[MethodKind::Password][..])
    ));

    let bob = session.authenticate_none("bob").await.unwrap();

    if let client::AuthResult::Failure {
        remaining_methods, ..
    } = bob {
        assert!(
            remaining_methods.contains(&MethodKind::PublicKey),
            "server reused Alice's narrowed remaining methods for Bob: {remaining_methods:?}"
        );
    }
}

On upstream/main, this fails with:

server reused Alice's narrowed remaining methods for Bob: MethodSet([Password])

That failure is produced by russh's retained AuthRequest.methods; it does not depend on handler-owned MFA/session state.

Impact

Suggested provisional CVSS v3.1:

  • CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:L/A:N
  • Score: 5.3

Reasoning:

  • AV:N: reachable by a remote SSH client during authentication.
  • AC:L: the attack is a normal sequence of SSH user-auth packets.
  • PR:N: the attacker does not need an already-authenticated SSH session.
  • UI:N: no user interaction is required on the…
Record
GHSA-hpv4-5h6f-wqr3
CVSS 3.1
5.3 MediumCVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:L/A:N
Weakness
CWE-287
Updated
2026-11-02

Affected products

Affected packages

Affected packages
PackageAffectedFixed
russh
crates.io
0.34.0-beta.1 up to 0.61.0
0.61.0
rust-russh
Debian:14
before 0.64.1-1, plus listed versions
0.57.1-10.57.1-2
0.64.1-1

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-46705 is a medium vulnerability (CVSS 5.3) in Eugeny Russh, published May 29, 2026. No source lists public exploit code. EPSS puts the chance of exploitation in the next 30 days at 0.22%, the 12th percentile. Fixed in russh 0.61.0.

References

This page doesn't list everything

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

MoveEnter Open