{"id":"CVE-2026-128087","kind":"vulnerability","aliases":["CVE-2026-128087","GHSA-9264-jvgf-6w2f"],"related":[],"title":"russh kex_done: Shared-secret callback runs before server host-key verification","description":"### Summary\n\nA malicious SSH server whose host key is rejected can still cause russh's `client::Handler::kex_done()` callback to execute with the raw key-exchange shared secret. Applications using the callback for its documented protocol-bridging purpose may derive keys, initialize a secondary data channel, or perform another externally visible action before russh calls `check_server_key()` and rejects the server.\n\n### Details\n\nDuring the initial key exchange, russh calls `kex_done()` immediately after the server proves possession of the presented host key, but before the application decides whether that key belongs to the intended server:\n\n```rust\nlet shared_secret = newkeys.kex.shared_secret_bytes();\nhandler\n    .kex_done(shared_secret, &newkeys.names, session)\n    .await?;\n\n// Initial KEX only checks trust afterwards.\nif let Some(certificate) = server_host_certificate {\n    if !handler.check_server_key(&certificate.into()).await? {\n        return Err(crate::Error::UnknownKey.into());\n    }\n} else if let Some(server_host_key) = server_host_key {\n    let check = handler.check_server_key(&server_host_key.into()).await?;\n    if !check {\n        return Err(crate::Error::UnknownKey.into());\n    }\n}\n```\n\nThis is in `russh/src/client/mod.rs` at lines 2036-2078 of commit `183a22e8f8f490fa09b6eb7bd044ef99d8c4414f`.\n\nThe API documentation describes `check_server_key()` as the important trust decision that prevents man-in-the-middle attacks. It describes `kex_done()` as the callback for deriving keys for secondary encrypted channels. The feature request that introduced the callback specifically lists VPN-over-SSH, UDP data planes, file transfer, and custom enterprise transports as intended uses.\n\nCryptographic verification of the KEX signature does not establish peer identity: an attacker operating its own SSH server can always produce a valid signature with its own host key. Identity is established only when `check_server_key()` accepts that key or certificate.\n\n### Expected behavior\n\nFor the initial key exchange, `check_server_key()` should accept the server identity before `kex_done()` exposes the shared secret for secondary-channel initialization.\n\n### Actual behavior\n\n`kex_done()` runs first. An untrusted server can therefore trigger application-defined secondary-channel actions even though `check_server_key()` subsequently rejects it with `UnknownKey`.\n\nThe callback was introduced by commit `500bef1eccc1c48ac674e2a262aa7887777431eb` and is present from `v0.55.0` through current `v0.65.0`.\n\n### Proof of concept\n\nThe following self-contained Cargo project starts a local russh server with a fresh, untrusted host key. The client models the documented bridge use case by exporting the shared secret in `kex_done()`, while `check_server_key()` rejects the server. It asserts both the failed connection and the callback order.\n\nCreate an empty directory and add `Cargo.toml`:\n\n```toml\n[package]\nname = \"russh-kex-before-host-trust-poc\"\nversion = \"0.1.0\"\nedition = \"2024\"\n\n[dependencies]\nrand = { version = \"0.10\", features = [\"thread_rng\"] }\nrussh = \"=0.65.0\"\ntokio = { version = \"1\", features = [\"macros\", \"net\", \"rt-multi-thread\"] }\n```\n\nCreate `src/main.rs`:\n\n```rust\nuse std::sync::{Arc, Mutex};\n\nuse russh::keys::{Algorithm, PrivateKey, PublicKeyOrCertificate};\nuse russh::{Names, client, server};\n\n#[derive(Clone)]\nstruct TestServer;\n\nimpl server::Handler for TestServer {\n    type Error = russh::Error;\n}\n\n#[derive(Clone)]\nstruct RejectingClient {\n    events: Arc<Mutex<Vec<&'static str>>>,\n    exported_secret: Arc<Mutex<Option<Vec<u8>>>>,\n}\n\nimpl client::Handler for RejectingClient {\n    type Error = russh::Error;\n\n    async fn kex_done(\n        &mut self,\n        shared_secret: Option<&[u8]>,\n        _names: &Names,\n        _session: &mut client::Session,\n    ) -> Result<(), Self::Error> {\n        self.events.lock().unwrap().push(\"kex_done\");\n\n        // Model a bridge exporting KEX material to a secondary protocol.\n        *self.exported_secret.lock().unwrap() = shared_secret.map(ToOwned::to_owned);\n        Ok(())\n    }\n\n    async fn check_server_key(\n        &mut self,\n        _server_public_key: &PublicKeyOrCertificate,\n    ) -> Result<bool, Self::Error> {\n        self.events.lock().unwrap().push(\"check_server_key\");\n        Ok(false)\n    }\n}\n\n#[tokio::main]\nasync fn main() {\n    let mut server_config = server::Config::default();\n    server_config.inactivity_timeout = None;\n    server_config\n        .keys\n        .push(PrivateKey::random(&mut rand::rng(), Algorithm::Ed25519).unwrap());\n    let server_config = Arc::new(server_config);\n\n    let listener = tokio::net::TcpListener::bind(\"127.0.0.1:0\").await.unwrap();\n    let address = listener.local_addr().unwrap();\n    tokio::spawn(async move {\n        let (stream, _) = listener.accept().await.unwrap();\n        let _ = server::run_stream(server_config, stream, TestServer).await;\n    });\n\n    let events = Arc::new(Mutex::new(Vec::new()));\n    let exported_secret = Arc::new(Mutex::new(None));\n    let client = RejectingClient {\n        events: events.clone(),\n        exported_secret: exported_secret.clone(),\n    };\n\n    let result = client::connect(\n        Arc::new(client::Config::default()),\n        address,\n        client,\n    )\n    .await;\n\n    println!(\"connection accepted: {}\", result.is_ok());\n    println!(\"callback order: {:?}\", events.lock().unwrap());\n    println!(\n        \"secret exported before rejection: {}\",\n        exported_secret.lock().unwrap().is_some()\n    );\n\n    assert!(matches!(result, Err(russh::Error::UnknownKey)));\n    assert_eq!(\n        events.lock().unwrap().as_slice(),\n        &[\"kex_done\", \"check_server_key\"]\n    );\n    assert!(exported_secret.lock().unwrap().is_some());\n}\n```\n\nRun:\n\n```sh\ncargo run --quiet\n```\n\nObserved with russh `v0.65.0`:\n\n```text\nconnection accepted: false\ncallback order: [\"kex_done\", \"check_server_key\"]\nsecret exported before rejection: true\n```\n\nThe connection fails with `russh::Error::UnknownKey`, but the security-sensitive callback and its modeled external side effect have already occurred.\n\n### Impact\n\nApplications overriding `kex_done()` to bootstrap a secondary encrypted transport are affected. An unauthenticated attacker who can impersonate the SSH endpoint can complete KEX with an attacker-owned host key and trigger secondary channel initialization before that key is rejected. Depending on the bridge, this can expose early secondary-channel data or make the application act on a session established with an untrusted peer.\n\nOrdinary clients that leave `kex_done()` at its no-op default, or implementations that independently defer all callback-derived actions until host trust has been confirmed, are not affected.","summary":"russh, a Rust SSH library, calls the kex_done callback with the raw key-exchange shared secret before check_server_key rejects an untrusted host key. An attacker impersonating an SSH server can trigger actions in applications that use kex_done to set up secondary channels.","severity":"low","cvss":3.7,"epss":null,"exploited":false,"exploited_at":null,"products":[{"name":"russh","fixed":["0.65.1"],"affected":">= 0.55.0, < 0.65.1","ecosystem":"cargo"}],"ecosystems":["cargo"],"tags":["cwe-696","cwe-863","package","russh","rust","ssh-client"],"not_affected_if":["default-config","kex-done-noop"],"how_to_check":"- Check the russh version in Cargo.lock or `cargo tree -i russh`; affected range is `>= 0.55.0, < 0.65.1`.\n- Search the codebase for `kex_done` overrides in `client::Handler` implementations; ordinary clients that leave the default no-op are not affected.","fix":"- russh: `0.65.1`","status":"open","published_at":"2026-11-13T19:19:31+00:00","first_seen_at":"2026-11-13T19:23:54+00:00","triaged_at":"2026-11-13T19:24:45+00:00","updated_at":"2026-11-13T19:52:09+00:00","category":"package","confidence":0.8,"triage":{"at":"2026-11-13T19:24:45Z","model":"claude-haiku-5-5","output":{"fix":"- russh: `0.65.1`","reach":"network","title":"russh: key-exchange callback runs before SSH server identity is checked","impact":"low","summary":"russh, a Rust SSH library, calls the kex_done callback with the raw key-exchange shared secret before check_server_key rejects an untrusted host key. An attacker impersonating an SSH server can trigger actions in applications that use kex_done to set up secondary channels.","audience":"developers","category":"package","nicknames":[],"who_cares":["rust","russh","ssh-client"],"confidence":0.8,"fix_status":"available","needs_auth":"no","worst_case":"secondary channel starts with an untrusted server; early data exposed","analyst_note":"","how_to_check":"- Check the russh version in Cargo.lock or `cargo tree -i russh`; affected range is `>= 0.55.0, < 0.65.1`.\n- Search the codebase for `kex_done` overrides in `client::Handler` implementations; ordinary clients that leave the default no-op are not affected.","plain_action":"","product_name":"","needs_analyst":false,"not_affected_if":["default-config","kex-done-noop"],"who_is_affected":"Only applications that use the russh SSH client library and override the kex_done callback to bootstrap a secondary encrypted transport are exposed. Clients that leave kex_done at its no-op default, or that defer all such actions until host trust is confirmed, are not affected. The attacker must be able to impersonate the SSH endpoint.","user_interaction":"no","product_ecosystem":"","needs_special_setup":"yes","severity_if_unknown":"low"},"cost_usd":0.000982,"input_tokens":7083,"output_tokens":548,"severity_before":"low"},"analyst_status":null,"analyst_note":null,"search":"'-128087':17A,25A '-2026':16A,24A '-2078':253C '-696':28B '-863':30B '-9264':19A '0.1.0':501C '0.10':507C '0.65.0':512C '1':515C '183a22e8f8f490fa09b6eb7bd044ef99d8c4414f':256C '2024':503C '2036':252C '500bef1eccc1c48ac674e2a262aa7887777431eb':420C '6w2f':22A 'accept':353C,369C 'action':72B,138C,403C 'actual':385C 'add':488C 'afterward':203C 'algorithm':534C 'alway':335C 'anoth':135C 'api':258C 'applic':74B,114C,173C,398C 'application-defin':397C 'arc':529C,560C,567C 'assert':474C 'async':580C 'attack':65B,276C,328C 'await':197C,216C,238C 'behavior':359C,386C 'belong':178C 'bridg':123C,455C,606C 'byte':189C 'call':42B,141C,156C 'callback':7A,46B,103C,117C,283C,297C,415C,481C 'cargo':437C 'cargo.toml':489C 'case':457C 'caus':96C 'certif':207C,210C,357C 'certificate.into':215C 'channel':83B,132C,290C,383C,402C 'check':56B,142C,201C,233C,240C,261C,350C,365C,406C,467C 'client':36B,99C,451C,540C,572C,594C 'clone':543C,556C 'commit':255C,419C 'concept':431C 'connect':478C 'contain':436C 'crate':219C,243C 'creat':483C,523C 'cryptograph':316C 'current':427C 'custom':310C 'cve':15A,23A 'cwe':27B,29B 'data':131C,305C 'decid':174C 'decis':268C 'defin':399C 'depend':504C 'deriv':126C,285C,542C,555C 'describ':260C,278C 'detail':149C 'directori':486C 'document':120C,259C,454C 'done':3A,45B,78B,102C,158C,192C,280C,375C,388C,465C,583C,603C 'edit':502C 'els':222C 'empti':485C 'encrypt':289C 'enterpris':311C 'err':218C,242C 'error':220C,244C,552C,554C,577C,579C,598C 'establish':324C,347C 'even':404C 'event':559C 'exchang':52B,111C,154C,364C 'execut':105C 'expect':358C 'export':459C,565C,607C 'expos':376C 'extern':136C 'fail':477C 'featur':292C,508C,516C 'file':307C 'first':390C 'fn':581C 'follow':433C 'fresh':446C 'ghsa':18A 'handler':100C,190C,548C,573C 'handler.check':212C,234C 'host':12A,62B,90C,168C,209C,227C,230C,343C,448C,497C 'host-key':11A 'ident':326C,345C,372C 'immedi':159C 'imperson':66B 'impl':546C,571C 'import':266C 'initi':128C,152C,198C,362C,384C 'intend':181C,314C 'introduc':295C,417C 'jvgf':21A 'jvgf-6w2f':20A 'kex':2A,44B,77B,101C,157C,191C,199C,279C,320C,374C,387C,464C,495C,582C,602C,608C 'key':13A,51B,58B,63B,91C,110C,127C,144C,153C,169C,177C,214C,228C,231C,236C,263C,286C,344C,352C,355C,363C,367C,408C,449C,469C,533C 'key-exchang':50B,109C 'let':184C,205C,224C,232C 'librari':41B 'line':251C 'list':299C 'local':441C 'macro':517C 'malici':86C 'man':272C 'man-in-the-middl':271C 'materi':609C 'may':125C 'middl':275C 'model':452C,604C 'multi':521C 'mut':584C,593C 'mutex':530C,561C,568C 'name':492C,539C,590C,591C 'net':518C 'newkeys.kex.shared':187C 'newkeys.names':195C 'oper':329C 'option':569C,588C 'order':482C 'packag':31B,491C 'peer':325C 'perform':134C 'plane':306C 'poc':499C 'possess':164C 'present':167C,423C 'prevent':270C 'privatekey':535C 'produc':336C 'project':438C 'proof':429C 'protocol':122C,613C 'protocol-bridg':121C 'prove':163C 'publickeyorcertif':536C 'purpos':124C 'push':601C 'rand':505C 'raw':49B,108C 'reject':59B,93C,146C,410C,470C 'rejectingcli':558C,575C 'request':293C 'result':596C 'return':217C,241C 'rng':510C 'rt':520C 'rt-multi-thread':519C 'run':8A,389C 'russh':1A,26A,32B,37B,97C,140C,155C,442C,494C,511C,532C,538C,553C,578C 'russh-kex-before-host-trust-poc':493C 'russh/src/client/mod.rs':249C 'rust':33B,39B,183C,525C 'secondari':82B,130C,288C,382C,401C,612C 'secondary-channel':381C,400C 'secr':615C 'secret':6A,54B,113C,186C,188C,194C,379C,462C,566C,587C 'self':435C,585C,597C 'self-contain':434C 'self.events.lock':599C 'self.exported':614C 'server':10A,57B,69B,88C,143C,148C,162C,182C,208C,213C,226C,229C,235C,262C,333C,351C,366C,371C,393C,407C,443C,468C,472C,541C,547C 'server_host_key.into':237C 'session':196C,592C,595C 'set':80B 'share':5A,53B,112C,185C,193C,378C,461C,586C 'shared-secret':4A 'signatur':321C,339C 'specif':298C 'src/main.rs':524C 'ssh':35B,40B,68B,87C,303C,332C 'ssh-client':34B 'start':439C 'static':563C 'std':527C 'still':95C 'str':564C 'struct':544C,557C 'subsequ':409C 'summari':84C 'sync':528C 'testserv':545C,550C 'therefor':395C 'though':405C 'thread':509C,522C 'tokio':513C 'toml':490C 'transfer':308C 'transport':312C 'trigger':71B,396C 'trust':202C,267C,498C 'type':551C,576C 'u8':589C 'udp':304C 'unknownkey':413C 'unknownkey.into':221C,245C 'untrust':61B,392C,447C 'unwrap':600C 'use':76B,115C,315C,456C,526C,531C,537C 'v0.55.0':425C 'v0.65.0':428C 'valid':338C 'vec':562C,570C 'verif':14A,317C 'version':500C,506C,514C 'visibl':137C 'vpn':301C 'vpn-over-ssh':300C 'whether':175C 'whose':89C","nicknames":[],"mitigations":[],"who_affected":"Only applications that use the russh SSH client library and override the kex_done callback to bootstrap a secondary encrypted transport are exposed. Clients that leave kex_done at its no-op default, or that defer all such actions until host trust is confirmed, are not affected. The attacker must be able to impersonate the SSH endpoint.","tier":"C","verified":{},"analyst_revisit_at":null,"fix_status":"available","audience":"developers","plain_action":null,"pkeys":["russh"],"ptokens":["russh"],"labels":["cargo","cwe696","cwe863","low","package","russh","rust","sshclient"],"campaign_type":null,"search_a":"'-128087':17A,25A '-2026':16A,24A '-9264':19A '6w2f':22A 'callback':7A 'cve':15A,23A 'done':3A 'ghsa':18A 'host':12A 'host-key':11A 'jvgf':21A 'jvgf-6w2f':20A 'kex':2A 'key':13A 'run':8A 'russh':1A,26A 'secret':6A 'server':10A 'share':5A 'shared-secret':4A 'verif':14A","search_b":"'-696':28B '-863':30B 'action':72B 'applic':74B 'attack':65B 'call':42B 'callback':46B 'channel':83B 'check':56B 'client':36B 'cwe':27B,29B 'done':45B,78B 'exchang':52B 'host':62B 'imperson':66B 'kex':44B,77B 'key':51B,58B,63B 'key-exchang':50B 'librari':41B 'packag':31B 'raw':49B 'reject':59B 'russh':32B,37B 'rust':33B,39B 'secondari':82B 'secret':54B 'server':57B,69B 'set':80B 'share':53B 'ssh':35B,40B,68B 'ssh-client':34B 'trigger':71B 'untrust':61B 'use':76B","search_c":"'-2078':253C '0.1.0':501C '0.10':507C '0.65.0':512C '1':515C '183a22e8f8f490fa09b6eb7bd044ef99d8c4414f':256C '2024':503C '2036':252C '500bef1eccc1c48ac674e2a262aa7887777431eb':420C 'accept':353C,369C 'action':138C,403C 'actual':385C 'add':488C 'afterward':203C 'algorithm':534C 'alway':335C 'anoth':135C 'api':258C 'applic':114C,173C,398C 'application-defin':397C 'arc':529C,560C,567C 'assert':474C 'async':580C 'attack':276C,328C 'await':197C,216C,238C 'behavior':359C,386C 'belong':178C 'bridg':123C,455C,606C 'byte':189C 'call':141C,156C 'callback':103C,117C,283C,297C,415C,481C 'cargo':437C 'cargo.toml':489C 'case':457C 'caus':96C 'certif':207C,210C,357C 'certificate.into':215C 'channel':132C,290C,383C,402C 'check':142C,201C,233C,240C,261C,350C,365C,406C,467C 'client':99C,451C,540C,572C,594C 'clone':543C,556C 'commit':255C,419C 'concept':431C 'connect':478C 'contain':436C 'crate':219C,243C 'creat':483C,523C 'cryptograph':316C 'current':427C 'custom':310C 'data':131C,305C 'decid':174C 'decis':268C 'defin':399C 'depend':504C 'deriv':126C,285C,542C,555C 'describ':260C,278C 'detail':149C 'directori':486C 'document':120C,259C,454C 'done':102C,158C,192C,280C,375C,388C,465C,583C,603C 'edit':502C 'els':222C 'empti':485C 'encrypt':289C 'enterpris':311C 'err':218C,242C 'error':220C,244C,552C,554C,577C,579C,598C 'establish':324C,347C 'even':404C 'event':559C 'exchang':111C,154C,364C 'execut':105C 'expect':358C 'export':459C,565C,607C 'expos':376C 'extern':136C 'fail':477C 'featur':292C,508C,516C 'file':307C 'first':390C 'fn':581C 'follow':433C 'fresh':446C 'handler':100C,190C,548C,573C 'handler.check':212C,234C 'host':90C,168C,209C,227C,230C,343C,448C,497C 'ident':326C,345C,372C 'immedi':159C 'impl':546C,571C 'import':266C 'initi':128C,152C,198C,362C,384C 'intend':181C,314C 'introduc':295C,417C 'kex':101C,157C,191C,199C,279C,320C,374C,387C,464C,495C,582C,602C,608C 'key':91C,110C,127C,144C,153C,169C,177C,214C,228C,231C,236C,263C,286C,344C,352C,355C,363C,367C,408C,449C,469C,533C 'key-exchang':109C 'let':184C,205C,224C,232C 'line':251C 'list':299C 'local':441C 'macro':517C 'malici':86C 'man':272C 'man-in-the-middl':271C 'materi':609C 'may':125C 'middl':275C 'model':452C,604C 'multi':521C 'mut':584C,593C 'mutex':530C,561C,568C 'name':492C,539C,590C,591C 'net':518C 'newkeys.kex.shared':187C 'newkeys.names':195C 'oper':329C 'option':569C,588C 'order':482C 'packag':491C 'peer':325C 'perform':134C 'plane':306C 'poc':499C 'possess':164C 'present':167C,423C 'prevent':270C 'privatekey':535C 'produc':336C 'project':438C 'proof':429C 'protocol':122C,613C 'protocol-bridg':121C 'prove':163C 'publickeyorcertif':536C 'purpos':124C 'push':601C 'rand':505C 'raw':108C 'reject':93C,146C,410C,470C 'rejectingcli':558C,575C 'request':293C 'result':596C 'return':217C,241C 'rng':510C 'rt':520C 'rt-multi-thread':519C 'run':389C 'russh':97C,140C,155C,442C,494C,511C,532C,538C,553C,578C 'russh-kex-before-host-trust-poc':493C 'russh/src/client/mod.rs':249C 'rust':183C,525C 'secondari':130C,288C,382C,401C,612C 'secondary-channel':381C,400C 'secr':615C 'secret':113C,186C,188C,194C,379C,462C,566C,587C 'self':435C,585C,597C 'self-contain':434C 'self.events.lock':599C 'self.exported':614C 'server':88C,143C,148C,162C,182C,208C,213C,226C,229C,235C,262C,333C,351C,366C,371C,393C,407C,443C,468C,472C,541C,547C 'server_host_key.into':237C 'session':196C,592C,595C 'share':112C,185C,193C,378C,461C,586C 'signatur':321C,339C 'specif':298C 'src/main.rs':524C 'ssh':87C,303C,332C 'start':439C 'static':563C 'std':527C 'still':95C 'str':564C 'struct':544C,557C 'subsequ':409C 'summari':84C 'sync':528C 'testserv':545C,550C 'therefor':395C 'though':405C 'thread':509C,522C 'tokio':513C 'toml':490C 'transfer':308C 'transport':312C 'trigger':396C 'trust':202C,267C,498C 'type':551C,576C 'u8':589C 'udp':304C 'unknownkey':413C 'unknownkey.into':221C,245C 'untrust':392C,447C 'unwrap':600C 'use':115C,315C,456C,526C,531C,537C 'v0.55.0':425C 'v0.65.0':428C 'valid':338C 'vec':562C,570C 'verif':317C 'version':500C,506C,514C 'visibl':137C 'vpn':301C 'vpn-over-ssh':300C 'whether':175C 'whose':89C","cause_entry":null,"cause_path":null,"disclosures_checked_at":null,"first_public_at":"2026-11-03T16:38:00+00:00","kev":null,"cvss_vector":"CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:L/I:N/A:N","cvss_by":"GitHub","poc_count":0,"sources":[{"source":"ghsa","external_id":"GHSA-9264-jvgf-6w2f","url":"https://github.com/advisories/GHSA-9264-jvgf-6w2f","severity":"low","published_at":"2026-11-13T19:20:16+00:00","modified_at":"2026-11-13T19:20:17+00:00","first_seen_at":"2026-11-13T19:23:54+00:00","fetched_at":"2026-11-13T19:24:33+00:00","note":null},{"source":"nvd","external_id":"CVE-2026-128087","url":"https://nvd.nist.gov/vuln/detail/CVE-2026-128087","severity":null,"published_at":"2026-11-13T19:19:31+00:00","modified_at":"2026-11-13T19:19:31+00:00","first_seen_at":"2026-11-13T19:52:09+00:00","fetched_at":"2026-11-13T19:52:10+00:00","note":null}],"documents":[{"id":148909,"url":"https://api.github.com/repos/Eugeny/russh/security-advisories/GHSA-9264-jvgf-6w2f","title":"Maintainer's advisory: api.github.com","kind":"vendor","source":"ghsa","publisher":"vendor","text":null,"published_at":null,"relation":"advisory","confidence":null,"note":"Maintainer's advisory: api.github.com"},{"id":148910,"url":"https://github.com/Eugeny/russh/security/advisories/GHSA-9264-jvgf-6w2f","title":"Maintainer's advisory: github.com","kind":"vendor","source":"ghsa","publisher":"vendor","text":null,"published_at":"2026-11-03T16:38:00+00:00","relation":"advisory","confidence":null,"note":"Maintainer's advisory: github.com"},{"id":148743,"url":"https://github.com/Eugeny/russh/pull/808","title":"Patch: github.com","kind":"other","source":"ghsa","publisher":"vendor","text":null,"published_at":null,"relation":"fix","confidence":null,"note":"Patch: github.com"},{"id":148744,"url":"https://github.com/Eugeny/russh/commit/43a46d67a80a7355fcd2fb25e7e00d79aec8184c","title":"Patch: github.com","kind":"other","source":"ghsa","publisher":"vendor","text":null,"published_at":null,"relation":"fix","confidence":null,"note":"Patch: github.com"},{"id":148745,"url":"https://github.com/Eugeny/russh/releases/tag/v0.65.1","title":"Release: github.com","kind":"release","source":"ghsa","publisher":"vendor","text":null,"published_at":null,"relation":"fix","confidence":null,"note":"Release: github.com"}],"disclosures":[],"exploit_sources":[],"notice":"Free to read, with fair use of about 60 pages a minute. For higher limits or API access: sales@infrastack.ai"}