Your SSH Agent Follows VSCode to the Server

A fly.io post on HN explains what Remote-SSH really does with your SSH agent. Here's the risk, a two-minute audit, and the fix.

Share

Fly.io has a post on the Hacker News front page titled "VSCode's SSH Agent Is Bananas," and the title undersells it. If you develop on remote machines with Remote-SSH, your local SSH agent is probably reachable from the other side of the connection.

Most engineers shrug at agent forwarding: the private key never leaves the laptop, so what's the risk? The key was never the interesting part. Your identity is.

Why this matters

Your agent holds keys and signs challenges. Forwarding extends that service to the remote host: sshd opens a Unix socket there, and anything that can reach the socket can ask your agent to sign. Push to GitHub as you, hop to the bastion, pull from private registries — from a process you never started.

Remote-SSH makes it worse than a plain ssh -A because it's invisible and long-lived. The terminal, tasks, extensions, and git all run server-side under ~/.vscode-server, for sessions that last all day. Nobody would deliberately forward an agent to a shared box for eight hours. Remote-SSH does it without a prompt you'd notice.

How it works

On connect, sshd sets SSH_AUTH_SOCK on the remote to a socket that proxies back to your local agent over the encrypted channel. Signature requests travel; keys stay home. That's a sound design — for machines you fully trust.

The weak point is policy. A stock agent signs anything, for any requester, with every key it holds. There's no "only git@github.com" rule and no logging you'd ever inspect. Abuse leaves zero traces on your laptop.

Where this helps

  • Bastions: forwarding beats copying keys onto a jump host — the one legit use case. Scope it to that host and nothing else.
  • Cloned repos: a postinstall script or VSCode task runs remote-side, right where the socket lives, and can quietly push commits or probe infrastructure as you.
  • Shared staging: anyone with root can borrow your socket while you're attached. When the session ends, the evidence goes with it.
  • Customer boxes: pointing Remote-SSH at a machine you don't admin means trusting every root user on it.

Watch out

Disabling forwarding has a cost: remote-side git needs another auth path, usually per-host keys or a token. And this isn't VSCode-specific — ForwardAgent yes in ~/.ssh/config does the same, and tmux on the remote keeps the socket alive after you "disconnect."

Better mitigations: use ssh -J for bastions so your agent never lands on the middle box, and add friction to the agent itself — ssh-add -t 30m for short key lifetimes, -c or a 1Password/FIDO-style touch prompt so every signature needs you in the room.

Try it yourself

# On the remote box, from a VSCode terminal:
echo "$SSH_AUTH_SOCK"
ssh-add -l          # if this lists keys, they're usable here

# Socket sshd created for your session:
ls -la /tmp/ssh-*

# Back on your laptop — default off, opt in per host:
# ~/.ssh/config
#   Host *
#       ForwardAgent no
#   Host bastion.internal
#       ForwardAgent yes

# Cheap damage limit for your daily keys:
ssh-add -t 30m ~/.ssh/id_ed25519

TL;DR

  • What changed: a fly.io post on HN spells out how casually Remote-SSH exposes your agent on the remote host.
  • Why it matters: anything running remote-side can sign as you — push code, reach prod — without ever seeing your key.
  • Try today: run ssh-add -l on your remote box; if it prints keys, make ForwardAgent no the default and opt in per host.