[Bug 3869] New: Loading "only" an ssh certificate in ssh-agent with ssh-add unnecessarily loads the private key and always exits with an error even when successful

bugzilla-daemon at mindrot.org bugzilla-daemon at mindrot.org
Mon Sep 29 00:27:23 AEST 2025


https://bugzilla.mindrot.org/show_bug.cgi?id=3869

            Bug ID: 3869
           Summary: Loading "only" an ssh certificate in ssh-agent with
                    ssh-add unnecessarily loads the private key and always
                    exits with an error even when successful
           Product: Portable OpenSSH
           Version: 10.0p2
          Hardware: All
                OS: All
            Status: NEW
          Severity: minor
          Priority: P5
         Component: ssh-agent
          Assignee: unassigned-bugs at mindrot.org
          Reporter: brendan at swiftspirit.co.za

Technically the solution for this could be in one or both of `ssh-add`
and `ssh-agent`.

When `ssh-add`ing a key that has an accompanying certificate to the
ssh-agent, the certificate is automatically added. When the certificate
expires and the certificate *file* is replaced, ssh-agent is not aware
of this and thus keeps a cached copy of the old expired certificate.

The ssh client seems to automatically read the certificate from disk in
this scenario, thus avoiding the issue for most users. I've come across
this scenario because I am writing an application in golang that makes
use of the ssh agent if it is available but it does not make use of the
ssh client binary. I have thus had to write a workaround for this
scenario as the agent passes the expired certificate to the
application. My application then checks if there is a new non-expired
certificate available on disk.

In attempting to resolve this on the certificate renewal end, one could
run `ssh-add -C ~/.ssh/id_ed25519` to add only the certificate. But,
running this first tries to re-add the identity despite what the man
page says:

`-C      When loading keys into or deleting keys from the agent,
process certificates only and skip plain keys.`

Because it tries to load the identity, it unnecessarily requires the
passphrase when the identity is encrypted. The command does at least
fail semi-gracefully. It fails to replace the identity and then
successfully re-adds the certificate. It also exits with exit code 1,
which could be misinterpreted as an error despite that the command
technically succeeded.

brendan at foo.local ~ % ssh-add -dC ~/.ssh/id_ed25519        
Identity removed: /home/brendan/.ssh/id_ed25519-cert.pub ED25519-CERT
(brendan at foo.local)
brendan at foo.local ~ % ssh-add -C ~/.ssh/id_ed25519
Enter passphrase for /home/brendan/.ssh/id_ed25519: 
Could not add identity "/home/brendan/.ssh/id_ed25519": success
Certificate added: /home/brendan/.ssh/id_ed25519-cert.pub
(brendan at foo.local)
1 brendan at foo.local ~ % ssh-add -C ~/.ssh/id_ed25519
Enter passphrase for /home/brendan/.ssh/id_ed25519: 
Could not add identity "/home/brendan/.ssh/id_ed25519": success
Certificate added: /home/brendan/.ssh/id_ed25519-cert.pub
(brendan at foo.local)
1 brendan at foo.local ~ %

I see three scenarios that would resolve the immediate problem:

a) `ssh-add -C ~/.ssh/id_ed25519`, because of the `-C` parameter,
should automatically know that the identity should not be loaded. It
should skip the private key entirely and load only the renewed
certificate.

b) An alternative flag to explicitly allow you to "refresh" the
certificate (though one could argue that's what `-C` is for)

c) A change to ssh-agent that has it watch the certificate file for
changes and automatically refresh the certificate when the cached
version is expiring/expired.

I believe that a) would be fixing a real bug, while c) would be a
valuable enhancement.

-- 
You are receiving this mail because:
You are watching the assignee of the bug.


More information about the openssh-bugs mailing list