bugzilla-daemon at mindrot.org
2025-Sep-28 14:27 UTC
[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
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.
bugzilla-daemon at mindrot.org
2025-Sep-29 02:58 UTC
[Bug 3869] 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
https://bugzilla.mindrot.org/show_bug.cgi?id=3869
Damien Miller <djm at mindrot.org> changed:
What |Removed |Added
----------------------------------------------------------------------------
CC| |djm at mindrot.org
Status|NEW |RESOLVED
Resolution|--- |WONTFIX
--- Comment #1 from Damien Miller <djm at mindrot.org> ---
Except for this spurious error:
> Could not add identity "/home/brendan/.ssh/id_ed25519": success
Everything you describe here is intended behaviour.
ssh-agent does not monitor files for changes. It only receives keys
when the user loads them via ssh-add. It *can't* monitor local files,
as the keys being loaded may not even be on the same host as ssh-agent
(consider agent forwarding). Sometimes there is no file to monitor,
e.g. keys being loaded from standard input, from a PKCS#11 token or
from a FIDO device.
Likewise, loading a certificate *must* require the private key too.
There are two reasons for this.
The first reason is practical: ssh-agent is essentially a repository
for private keys and, in ssh-agent's view, certificates are just
another type of private key.
The second reason has to do with security. If it is possible to load a
certificate without the private key, then there is no proof that the
user loading the certificate has *access* to the private key material
that corresponds to that certificate. Relaxing this criteria would
allow, for example, an attacker on a machine to which a user had
forwarded their agent to load an unexpected certificate that could be
used with a previously-loaded private key. Under some circumstances,
this could be worse than the attacker having access to the agent at
all.
Sorry, we don't intend to change any of this. I will fix the spurious
error message though.
--
You are receiving this mail because:
You are watching the assignee of the bug.
You are watching someone on the CC list of the bug.
bugzilla-daemon at mindrot.org
2025-Sep-29 07:55 UTC
[Bug 3869] 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
https://bugzilla.mindrot.org/show_bug.cgi?id=3869 --- Comment #2 from Brendan Hide <brendan at swiftspirit.co.za> ---> If it is possible to load a certificate without the private key, then there is no proof that the user loading the certificate has *access* to the private key material that corresponds to that certificate.Perhaps I don't understand the security model well. If the agent has a certificate and the client tries to load a new one with a matching pubkey+signer/etc (and with a newer expiry date), I'm not sure it really matters that the client doesn't have access to the private key. As a parallel, cert issuers never have access to your private keys, only your public keys. -- You are receiving this mail because: You are watching the assignee of the bug. You are watching someone on the CC list of the bug.