CVE-2026-128088
### Summary In russh `0.65.0`, a sign request for a confirmation-constrained key can retain and use the private key after another connection locks the agent. `try_sign()` snapshots an `Arc<PrivateKey>` before awaiting `Agent::confirm()` and does not revalidate the shared lock state after the await. An agent-forwarding peer can therefore obtain a signature while the agent is locked and every new request is being rejected. ### Details The agent's lock and key stores are shared by all connections. `respond()` reads the lock state once, then dispatches a sign request: ```rust let is_locked = { // ... read the shared lock ... }; // ... Some((&13, mut r)) if !is_locked && agentref.confirm_request(MessageType::Sign).await => { let agent = self.agent.take().ok_or(Error::AgentFailure)?; let (agent, signed) = self.try_sign(agent, &mut r, writebuf).await?; ``` In `try_sign()`, russh clones the private key from the shared store and drops the store lock before awaiting the asynchronous confirmation callback: ```rust let key = { let blob = Bytes::decode(r)?; let k = self.keys.0.read().or(Err(Error::AgentFailure))?; if let Some((key, _, constraints)) = k.get(&blob.to_vec()) { if constraints.contains(&Constraint::Confirm) { needs_confirm = true; } key.clone() } else { return Ok((agent, false)); } }; let agent = if needs_confirm { let (agent, ok) = agent.confirm(key.clone()).await; if !ok { return Ok((agent, false)); } agent } else { agent }; // No lock/key-state revalidation occurs here. sign_with_hash_alg(&PrivateKeyWithHashAlg::new(key, hash_alg), &data)? .encode(writebuf)?; ``` While `confirm()` is pending, a second agent connection can successfully lock the shared agent. When confirmation later returns `true`, the original connection signs with its captured `Arc<PrivateKey>`. The affected code is in [`russh/src/keys/agent/server.rs`](https://github.com/Euge
Properties
- Summary
- russh try_sign: asynchronous confirmation can sign after agent lock
- Severity
- low
- Nvd fetched at
- 2026-11-14T00:40:25.638091+00:00
- Cvss score
- 2.2
- Cvss severity
- LOW
- Retrieved at
- 2026-11-14T00:50:08+00:00
- Ghsa published
- 2026-11-13T19:10:46Z
- Source url
- https://github.com/advisories/GHSA-736f-c93q-9fwx
- Ghsa updated
- 2026-11-13T19:10:47Z
- Ghsa id
- GHSA-736f-c93q-9fwx
- Last source
- GitHub Advisory Database
- Score
- 2.2
- Cvss version
- 3.1
- Cve id
- CVE-2026-128088
- Cvss vector
- CVSS:3.1/AV:L/AC:H/PR:L/UI:R/S:U/C:N/I:L/A:N
- First seen by Signal
- 2026-11-13T20:38:23+00:00
- Is ghsa only
- false
- Vector
- CVSS:3.1/AV:L/AC:H/PR:L/UI:R/S:U/C:N/I:L/A:N
- Published at
- 2026-11-13T19:19:31.630
- Last modified
- 2026-11-13T19:19:31.743
Related Entities (4)
HAS_WEAKNESS (2)
AFFECTS (1)
VULNERABLE_TO (1)
Related research
Explore deeper with Ninja Signal's threat intelligence graph