Skip to content

fix: Skip upstream agents that error when listing identities - #94

Merged
overhacked merged 1 commit into
overhacked:mainfrom
sini:fix/tolerate-upstream-list-errors
Jul 18, 2026
Merged

fix: Skip upstream agents that error when listing identities#94
overhacked merged 1 commit into
overhacked:mainfrom
sini:fix/tolerate-upstream-list-errors

Conversation

@sini

@sini sini commented Jul 17, 2026

Copy link
Copy Markdown
Contributor

Problem

refresh_identities already tolerates an upstream whose socket is missing or
refuses the connection — it 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 entire refresh, dropping every other agent's
keys 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_identities with
SSH_AGENT_FAILURE, both behind the mux:

# unpatched
$ SSH_AUTH_SOCK=$mux ssh-add -l
error fetching identities: agent refused operation      # the good agent's key is gone too

# patched
$ SSH_AUTH_SOCK=$mux ssh-add -l
256 SHA256:… testkey (ED25519)                          # bad upstream skipped, good key served

Fix

Handle a request_identities error the same way a missing socket is already
handled — log a warning and skip that upstream — so the remaining agents keep
working. One-line-of-logic change, mirroring the connect_upstream_agent error
arm directly above it.

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.
@sini sini changed the title Skip upstream agents that error when listing identities fix: Skip upstream agents that error when listing identities Jul 17, 2026
@overhacked
overhacked merged commit db09a76 into overhacked:main Jul 18, 2026
6 checks passed
@overhacked

Copy link
Copy Markdown
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.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants