fix: Skip upstream agents that error when listing identities - #94
Merged
overhacked merged 1 commit intoJul 18, 2026
Merged
Conversation
refresh_identities already tolerates an upstream whose socket is missing or refuses the connection (logs a warning and continues). But if an upstream socket is reachable and then returns an *error* to request_identities, the `?` propagated it and aborted the whole refresh, dropping every other agent's keys too. This happens in practice with agents that have partial ssh-agent protocol implementations, or one that is momentarily mid-restart: a single flaky upstream takes the mux down until it is restarted. Handle the list error the same way as a missing socket - warn and skip that upstream - so the remaining agents keep working.
Owner
|
THanks! |
sini
added a commit
to sini/ssh-agent-mux
that referenced
this pull request
Aug 14, 2026
overhacked#56) ssh-agent-lib 0.5.1 typed identities as ssh_key::public::KeyData, which cannot represent an OpenSSH certificate: request_identities decoded a ...-cert-v01@openssh.com blob into a lossy opaque key and re-serialized a truncated identity, so any upstream agent holding a certificate made `ssh-add -l` fail with "incomplete message" and (with overhacked#94) silently dropped every other agent's keys. Bump to ssh-agent-lib 0.6.0, whose PublicCredential (Key | Cert) round-trips certificates losslessly in both identity listings and sign requests. Key the known-keys map by credential.key_data() so a certificate, its bare public key, and the sign request ssh issues all resolve to the same upstream agent. Note: certificates with valid_before = u64::MAX ("Valid: forever") still fail to decode under the ssh-key 0.6.7 that ssh-agent-lib 0.6.0 builds on (RustCrypto/SSH#504, fixed in ssh-key 0.7). Certificates with a real expiration -- as OpenSSH and correctly configured issuers produce -- work now.
sini
added a commit
to sini/ssh-agent-mux
that referenced
this pull request
Aug 14, 2026
overhacked#56) ssh-agent-lib 0.5.1 typed identities as ssh_key::public::KeyData, which cannot represent an OpenSSH certificate: request_identities decoded a ...-cert-v01@openssh.com blob into a lossy opaque key and re-serialized a truncated identity, so any upstream agent holding a certificate made `ssh-add -l` fail with "incomplete message" and (with overhacked#94) silently dropped every other agent's keys. Bump to ssh-agent-lib 0.6.0, whose PublicCredential (Key | Cert) round-trips certificates losslessly in both identity listings and sign requests. Key the known-keys map by credential.key_data() so a certificate, its bare public key, and the sign request ssh issues all resolve to the same upstream agent. Note: certificates with valid_before = u64::MAX ("Valid: forever") still fail to decode under the ssh-key 0.6.7 that ssh-agent-lib 0.6.0 builds on (RustCrypto/SSH#504, fixed in ssh-key 0.7). Certificates with a real expiration -- as OpenSSH and correctly configured issuers produce -- work now.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
refresh_identitiesalready tolerates an upstream whose socket is missing orrefuses the connection — it logs a warning and
continues. But if an upstreamsocket is reachable and then returns an error to
request_identities, the?propagated it and aborted the entire refresh, dropping every other agent'skeys too (and failing the client's list/sign).
This happens with an agent that has a partial ssh-agent protocol implementation
(e.g. rbw's Bitwarden ssh-agent), or one that is momentarily mid-restart: a
single flaky upstream takes the whole mux down until it is restarted.
Reproduction
A good agent plus one upstream that answers
request_identitieswithSSH_AGENT_FAILURE, both behind the mux:Fix
Handle a
request_identitieserror the same way a missing socket is alreadyhandled — log a warning and skip that upstream — so the remaining agents keep
working. One-line-of-logic change, mirroring the
connect_upstream_agenterrorarm directly above it.