Security Hygiene

SSH Agent Forwarding Lends Your Keys to Every Host You Visit

July 28, 2026 7 min read Haven Team

The reassuring thing people say about agent forwarding is that your private key never leaves your laptop. That part is true. What gets left out is that the remote host receives something functionally equivalent for the duration of your session: a socket that will sign anything it is asked to sign, with your key, on your behalf, and tell you nothing about it.


The setup is familiar to anyone who administers more than one machine. You keep your key on your laptop, unlocked in ssh-agent. You connect to a jump box. From there you need to reach a second machine, or pull from a private git repository, and you would rather not copy your key onto the jump box. So you pass -A, or set ForwardAgent yes, and authentication from the jump box simply works.

What happens underneath: the SSH client on the far end creates a Unix domain socket, sets SSH_AUTH_SOCK in your shell environment to point at it, and tunnels everything written to that socket back down the connection to the agent on your laptop. When something on the remote host needs a signature, it writes a challenge into the socket, your laptop's agent signs it, and the signature comes back.

The key material genuinely stays put. The capability does not.

Who can use the socket

The socket lives in a directory owned by you with restrictive permissions, which stops other unprivileged users on the box. It does not stop root. Anyone with root on that machine, or anyone who has compromised a process running as your user, can set SSH_AUTH_SOCK to your socket path and start authenticating as you to anything your key opens.

They cannot extract the key, so the window closes when you disconnect. Inside that window the difference is academic. Your agent will happily sign a challenge from your production database host while you are reading logs on a staging box, and the default configuration gives you no prompt, no log line, and no indication afterwards that it happened.

The mental model to replace

Agent forwarding is not "my key stays safe." It is "for the next twenty minutes, this machine can authenticate as me anywhere my key is authorised, and I will not be told when it does." Whether that trade is acceptable depends entirely on who else has access to the machine.

The Matrix.org breach is the worked example

In April 2019 the Matrix.org homeserver infrastructure was compromised. The published post-mortem describes an entry point through a vulnerable Jenkins instance, and then a lateral move that used a forwarded SSH agent from an administrator session on that host to reach production systems. The attacker did not need to crack a key. Somebody had connected to the CI box with forwarding on, and the credential was there for the taking.

This is the usual sequence. The forwarded agent is rarely the initial compromise. It is the thing that turns a foothold on a low-value machine into access on a high-value one, which is exactly the boundary a jump host is supposed to enforce.

CI runners are the most common offender: shared, frequently patched late, running third-party build steps, and administered by people who forward agents out of habit. The same reasoning applies to a shared bastion, a colleague's workstation, and any host whose administrators you have not personally vetted. The pattern belongs to the same family as supply chain compromise: the trust you extend to a system quietly becomes trust extended to everyone who has ever had a shell on it.

ProxyJump does the thing you actually wanted

Most agent forwarding exists to solve a routing problem: the target is only reachable through an intermediate host. That has had a proper solution since OpenSSH 7.3 in 2016, and it does not involve exposing your agent at all.

ssh -J bastion.example.com target.internal, or a ProxyJump line in your config, tells your local client to open a connection to the bastion and then tunnel a second, independent SSH session through it to the target. Both authentication handshakes happen on your laptop. The bastion forwards encrypted bytes and never sees a signing request, because there is nothing on the bastion to send one.

Agent forwarding ProxyJump
Private key location Local only Local only
Intermediate host can authenticate as you Yes, for the session No
Host key of the target verified by you No, by the intermediate Yes, locally
Works for git operations run on the remote host Yes No, different problem

That last row is the real limitation. If you need to run git pull on the remote machine against a private repository, ProxyJump does not help, because the process needing credentials is genuinely over there. That case deserves its own credential: a deploy key scoped to one repository, or a short-lived certificate, rather than the key that opens your entire estate.

When you do forward, narrow it

The general principle

Delegation and disclosure are different risks, and this feature confuses them. Copying a key to a server is disclosure and everybody recognises it as bad. Forwarding an agent is delegation, it feels safe because nothing is copied, and it hands out a live capability instead of a stored secret. The capability is time-bounded, and within its window it is the same power.

The useful question before typing -A is not "do I trust this machine with my key," because you are not giving it your key. It is: do I trust everyone who currently has root on this machine to authenticate as me for the next hour? On your own laptop the answer is yes. On a shared CI runner the answer is almost certainly no, and that is the machine where people forward most often.

Try Haven free for 15 days

Encrypted email and chat in one app. No credit card required.

Get Started →