Restricting SSH Agent Keys

[LWN subscriber-only content]

Welcome to

The following subscription-only content has been made available to you
by an LWN subscriber. Thousands of subscribers depend on LWN for the
best news from the Linux and free software communities. If you enjoy this
article, please consider accepting the trial offer on the right. Thank you
for visiting!

Free trial subscription

Try LWN for free for 1 month: no payment
or credit card required. Activate
your trial subscription now
and see why thousands of
readers subscribe to


By Jake Edge

January 5, 2022

The OpenSSH suite of tools for
secure remote logins is used widely within our communities; it also
underlies things like remote Git repository access.
A recent experimental feature for the upcoming OpenSSH 8.9 release
will help close a security hole
that can be exploited by attacker-controlled SSH servers (e.g. sshd) when the user is forwarding
authentication to a local ssh-agent. Instead
of allowing the keys held in the agent to be used for authenticating to any
host where they might work, SSH agent
will allow users to specify where and how those keys can be

The ssh-agent is used to
to simplify making repeated connections to the same host; it stores and
manages SSH keys so that the passphrases protecting them do not need to be
entered each time a connection is made. Normally, the passphrase is used
once to unlock a key, which then gets stored by the agent when ssh-add is used;
alternatively, the ssh_config option
can be used for the same purpose. ssh-agent is a
deliberately simple program” since it holds private keys.
Damien Miller’s description of the new feature (linked above) described it
this way:

It speaks a simple, client-initiated protocol
with a small number of
operations including adding or deleting keys, retrieving a list of public
halves for loaded keys and, critically, making a signature using a private
key. Most interactions with the agent are through the ssh-add tool for
adding, deleting and listing keys and ssh, which can use keys held in an
agent for user authentication, but other tools can also be used if they
speak the protocol.

Since the agent contains high-value keys, it is “a desirable and
frequently-exploited target for attackers
“. The agent is only
accessible from the local system, which greatly limits the attack surface,
unless access to the agent has been forwarded to a remote system. Using
the -A option to ssh (or the ForwardAgent
configuration directive) will arrange for the remote host to be able to
communicate with the local agent. That remote host can then perform all of the agent
operations in the same way that local programs can.

This kind of agent forwarding is generally used so that multi-hop SSH
connections can be made without needing to re-enter the passphrase to
unlock the key on the remote host—possibly many times. It also means that
the private keys do not need to stored on the remote hosts. A user who remotely
connects to HostA, and from there to one or more other hosts using the same
SSH key, will likely find it convenient to make the initial SSH connection
to HostA with agent-forwarding enabled; SSH connections from HostA may extend
the agent-forwarding path, as well.

The problem occurs when agent access is forwarded to an attacker-controlled
system that then can use the keys stored in the agent to authenticate to
any other host the user’s keys give them access to. So the user may be
using forwarding for HostA, HostB, and HostC, but their key will grant them
access to HostV or HostZ that an attacker wants to target for some reason.
Currently, SSH has no way to restrict how the keys held by the agent can be
used; that is the problem that the new feature is meant to address.

Part of the solution is separating local access from remote access to the
agent, so that some keys can only be used from the local system even if
agent access is forwarded. Arguably, conflating those two types of agent access was a
mistake made long ago, so being able to add keys with restrictions on how
they can be used will help to rectify that. A new -h option has been
created for ssh-add to describe the legal uses of a key, as an
example from the feature description shows:

These extensions allow the user to add destination constraints to keys
they add to a ssh-agent and have ssh enforce them. For example, this

    $ ssh-add -h "" 
              -h "" 
    	      -h ">" 

Adds a key that can only be used for authentication in the following circumstances:

  1. From the origin host to as any user.
  2. From the origin host to as user perseus.
  3. Through to host as user medea.

Attempts to use this key to authenticate to other hosts will be refused by
the agent because they weren’t explicitly listed, as would an attempt to
authenticate through to because the
path was not permitted. Likewise, trying to authenticate as any other user
then perseus to or medea to would
fail because the destination users are not permitted.

More complicated paths can be specified, but each hop needs to be listed in
its own -h option. So a multi-hop path might look something like:

    $ ssh-add -h "HostA" 
              -h "HostA>HostB" 
    	      -h "HostB>HostC" 

It should be noted that an agent configuration like the above would not allow the
agent’s key to be used to go directly from the local system to HostB or
HostC, they could only be reached via the appropriate hops. The user may
still be able to bypass the agent and fall back to typing in the passphrase
for the key when prompted by


in order to go
directly to HostB or HostC, however.

The new feature requires updates to the client-side tools, but also
needs updated SSH servers on the remote systems. The agent protocol
needed to change to incorporate
the server host key
in the authentication requests, so older SSH
servers will not be able to participate in the new scheme. The feature
will “fail safe” if ssh-add or the SSH server do not support the
agent restrictions; ssh-add will fail if it does not understand
the destination constraints and the agent will decline authentication
requests that are not sent with the host key.

There are some caveats. The biggest is that attackers can still hijack the
agent connection so they can request authentication to hosts (and
users) that have been authorized, but from different hosts than expected:

Less obviously, they will also be able to forward use of the agent to other
hosts, e.g. by using an SSH implementation that doesn’t cooperate with
ssh-agent, or another tool entirely, such as socat. Note that the attacker
isn’t gaining any new access to keys here, they are still forced to act via
the compromised host and their access is still restricted to the keys that
were permitted for use though the intended host only.

[…] Because of these subtleties, it’s better to think of key constraints
as permitting use of a key through a given host rather than as from a
particular host, and, more generally, that any forwarding path is only as
strong as its weakest link. Another helpful way to think about key
constraints is that each one represents a delegation of a key to a host,
that is only slightly more trustworthy than the delegate is.

Overall, this seems like a welcome addition to the SSH toolbox; the
restrictions provided will be useful. It is nice to know that agent
forwarding will no longer provide carte blanche access to any host where
the key will work. The document describing the feature is admirably
detailed, with a look at the implementation details, plans for the future,
and more. Interested readers are encouraged to take a look.

Did you like this article? Please accept our
trial subscription offer to be
able to see more content like it and to participate in the discussion.

(Log in to post comments)

Join the pack! Join 8000+ others registered users, and get chat, make groups, post updates and make friends around the world!
Read More


1 Comment

  1. Instead of forwarding the ssh agent I use a bastion host and proxycommand. That lets me keep the ssh private key on the outermost host.

    The outer system has the key, and the inner bastion system has the acl to connect inward to actual servers. Works well.