I spent a chunk of my career wiring up enterprise CMS platforms where a single over-scoped service account could ruin your whole quarter. So when I saw that a popular AI desktop app was forwarding people’s SSH agent to remote machines, my first reaction wasn’t shock. It was a tired kind of recognition. We keep handing convenience tools the keys to everything and then acting surprised when the keys end up somewhere we didn’t expect.
The specific issue is simple to describe. You install an AI assistant as a desktop app. It can open a terminal, run commands, connect to your servers. To make that smooth, it leans on your existing SSH setup. And if your SSH agent is forwarded, the credentials that live in that agent can travel to whatever box the tool connects to. That is a lot of trust to extend to software that also talks to a model you don’t control.
Agent forwarding was always a loaded gun
SSH agent forwarding predates any of this AI stuff. The idea is reasonable on paper: you connect to server A, and from A you need to reach server B using the same key, so your local agent answers the challenge over the forwarded channel. No private key ever leaves your laptop. Nice.
The catch has been known for years. Anyone with root on server A, or any process running as you on server A, can talk to that forwarded socket while your session is open. They can’t copy the key, but they don’t need to. They can just ask the agent to sign things. For as long as you’re connected, your key is effectively usable by whoever controls the far end.
Security folks have warned about this forever. The usual advice is to not forward your agent by default, use ForwardAgent no, and only enable it per-host when you actually trust the destination. Most developers I know ignore that advice because forwarding is convenient and nothing bad has happened yet. That is the whole genre of security incident, really. Nothing bad happens, until a new actor shows up in the chain.
The new actor is a program that reasons
Here’s what changed. The destination used to be a server you chose. Now part of the chain is an AI app making decisions about what commands to run and where to run them. The model can be steered. It reads files, web pages, repo contents, issue comments, anything you point it at. Prompt injection is not a hypothetical. People have been demonstrating it against coding agents all year, where a poisoned README or a crafted comment convinces the assistant to do something its owner never asked for.
Now connect those two facts. An assistant that can be nudged by untrusted text, holding a live line to your forwarded SSH agent, with the ability to open connections. You don’t have to imagine a dramatic breach. You just have to imagine the assistant doing exactly what it was told to do by some text it read, using credentials it was never supposed to have reach over.
I’m not saying this gets exploited at scale tomorrow. I’m saying the blast radius is now much larger than anyone signed up for when they clicked install.
Convenience is the real attack surface
The thing that makes these tools great is the same thing that makes them dangerous. They inherit your environment. They run as you. They see your dotfiles, your environment variables, your cloud CLI sessions that are already authenticated, your git credentials, your shell history with that one API token you pasted in six months ago and forgot about.
From a threat-modeling view, a desktop AI app is one of the most privileged pieces of software on your machine. It has:
- Shell execution, so it can run anything your user can run
- Filesystem access, which includes your
~/.ssh, your~/.aws, your.envfiles - Network reach, outbound, to anywhere
- A reasoning layer that can be influenced by content you feed it
We would never ship an enterprise service with that profile and no guardrails. We’d scope its permissions, run it in a sandbox, give it a service account with the narrowest rights that still let it do the job. But on our own laptops we skip all of that because it’s our personal machine and the tool is helpful and setup is annoying.
What I’d actually check
I went through my own setup after reading about this, and it was a useful hour. A few things worth doing if you run any AI desktop app that can touch a terminal.
Start with your SSH config. Open ~/.ssh/config and look for ForwardAgent yes, especially if it’s set under a wildcard Host * block. If it’s on globally, turn it off and only enable it for the specific hosts where you genuinely need it. Your future self will thank you the first time an assistant does something weird.
Check what the app can reach. Some of these tools let you restrict which directories they can read and which commands they can run. If yours has an allow-list or a permission mode, use it. Running every action through an approval prompt feels slow for about a day, then it feels normal, and it catches the one command you didn’t mean to run.
Audit your shell environment for secrets sitting in plain text. Grep your history and your dotfiles for anything that looks like a token or a password. If an assistant can read your shell history, assume it has read every secret you ever pasted into a terminal. Rotate the ones that matter.
Think about running risky work in a container or a VM. When I’m letting an agent loose on a repo I don’t fully trust, I’d rather it be inside a disposable environment with no access to my real credentials. It’s more friction, but it turns a potential incident into a shrug and a rebuilt container.
This is a design problem, not a user problem
I don’t love the framing where every security story ends with a checklist for the user. Yes, you should harden your setup. But the deeper issue is that these apps ship with broad default access because broad access demos well. Nobody wants the onboarding flow where the assistant can’t do anything until you grant it seventeen permissions.
The tools that earn long-term trust will be the ones that treat your credentials as something to be protected from the tool itself, not just something the tool happily uses on your behalf. Least privilege by default. Explicit, visible escalation when more access is needed. A clear line between what the model can suggest and what it’s allowed to execute without you looking.
Until the defaults get better, the responsibility sits with us. If you’re going to give an AI app a seat at your terminal, treat it like onboarding a new contractor you’ve never met. Give it what it needs for the task in front of it, and nothing that would hurt if it turned out to have bad judgment. Because sometimes it will.
Go check your SSH config. It’ll take five minutes, and it’s a better use of your morning than reading one more take about model benchmarks.