Store your SSH keys in a Password Manager

- 6 min read

Hey folks, this one is a quick one, but first:

I have a speed bump phobia.
But I'm slowly getting over it now, which is nice.

Now, a quick suggestion: Store your SSH keys in a password manager, folks!

The Problem

It feels like every day, there's a new NPM hack that installs a malicious package on a developer's machine that steals their credentials, especially the private SSH keys that can be used to push to GitHub and SSH into connected servers. The worst part is that they won't notice it at all. The malware does a smash-and-grab: it fetches your private keys from ~/.ssh, uploads them to a command-and-control server, and leaves. This gives the attacker the time to change the code on their machine and push it back to GitHub and potentially to NPM and other package managers if the GitHub CI is set up to release new versions automatically.

The Solution

Just like you wouldn't store passwords in a text file on your computer, you shouldn't store your SSH keys as text files in .ssh either. Move them to a password manager!

I recently moved my SSH keys to Proton Pass, but other managers like 1Password support SSH keys as well. The setup process is pretty straightforward.

1. Move your SSH Keys to Proton Pass

First, copy your public and private SSH key pairs into the password manager. Proton Pass has a dedicated type under Create Item > Other > SSH Key. If your SSH key is password protected, either store the unencrypted version or store your decryption password in the same SSH key item as Password or Passphrase, but Proton Pass will try all hidden fields as passwords to decrypt the SSH key.

Next, install the Proton Pass CLI pass-cli and run pass-cli login.

Now, make sure that Proton Pass finds your SSH keys with:

> pass-cli ssh-agent debug --vault-name YourVaultName
SSH Agent Debug Report
Vault: YourVaultName (some-identifier)
Valid SSH Keys (2):
SSH - id_ed25519
Algorithm: Ed25519
Fingerprint: SHA256:some-fingerprint
SSH - RSA
Algorithm: RSA-3072
Fingerprint: SHA256:some-fingerprint

At this point, I suggest moving your ~/.ssh/id_* keys into a backup folder like ~/.ssh/backup/id_*. This will move them out of the .ssh folder that is used by ssh by default so that you can test the integration with Proton Pass.

2. Start the SSH Daemon

Proton Pass supports running an SSH agent as a daemon that allows tools like git and ssh to fetch the SSH keys automatically. You can start the daemon with:

> pass-cli ssh-agent daemon start --log-file ~/.ssh/proton-pass-agent.log
Daemon started (PID: 12345)
PID file: /Users/youruser/.ssh/proton-pass-agent.pid
Log file: /Users/youruser/.ssh/proton-pass-agent.log
Logs: discarded (use --log-file to capture them)
To connect to the agent, set SSH_AUTH_SOCK:
export SSH_AUTH_SOCK=/Users/youruser/.ssh/proton-pass-agent.sock

I added the optional --log-file argument here to store the agent's output to a log file. This makes it easier to debug and track SSH issues in the future.

Last step: Add this line to your shell's config like ~/.zshrc and restart your terminal session{}

export SSH_AUTH_SOCK="$HOME/.ssh/proton-pass-agent.sock"

Now you should see your SSH keys appear when you run:

> ssh-add -l
3072 SHA256:some-fingerprint SSH - RSA (RSA)
256 SHA256:another-fingerprint SSH - id_ed25519 (ED25519)

If you see an output like the one above, you're all set up now. You can run e.g. git pull on a private repo and should see that everything works as before.

3. Start the SSH Agent Automatically

If you restart your system, your SSH agent won't start automatically at this point. To fix this, follow the instructions for your operating system in the Proton docs.

On macOS, you have to do this:

Create the file at:

~/Library/LaunchAgents/com.proton.pass-cli.ssh-agent.plist

Add the following content to it:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN"
"http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>com.proton.pass-cli.ssh-agent</string>
<key>ProgramArguments</key>
<array>
<string>/Users/youruser/.local/bin/pass-cli</string>
<string>ssh-agent</string>
<string>start</string>
</array>
<key>RunAtLoad</key>
<true/>
<key>KeepAlive</key>
<true/>
</dict>
</plist>

Then load it:

launchctl load ~/Library/LaunchAgents/com.proton.pass-cli.ssh-agent.plist

And that's it! Your SSH agent should now start automatically when you restart your system.

4. (Optional) Fix ~/.ssh/config

If you have lines like IdentityFile ~/.ssh/id_ed25519 in your ~/.ssh/config you must either delete them or replace them with the following line:

Host somehost.com
- IdentityFile ~/.ssh/id_ed25519
- IdentitiesOnly yes
+ IdentityAgent ~/.ssh/proton-pass-agent.sock

One Caveat

Storing your SSH keys in a password manager doesn't make them completely inaccessible to your system and therefore: to attackers. If you run git push now, it will automatically fetch the SSH keys from Proton Pass to authenticate with GitHub. The only advantage here is that the SSH keys are no longer stored in a text file and malware can't simply copy and upload them. The downside is that malware can still execute commands like git push to push malicious code to your GitHub, or it can ssh into your server. The difference is that it now needs to execute these commands from your computer instead of from its warm and cosy home on the attacker's machine.

If you want to be even safer, there are two more steps you can take:

First, you can switch to 1Password which offers per-use biometric confirmation, which Proton Pass doesn't offer (yet). This means that you need to confirm every attempt to fetch your SSH keys with e.g. Touch ID or by typing your vault password. You can optionally set a timeframe in which you don't need to re-approve, which makes it easier to run multiple git commands without having to confirm each one in e.g. a 30-minute window.

I really hope that Proton Pass adds per-use biometric confirmations soon, but I have confidence given that they added SSH key support only recently.

Second, even safer than stored SSH keys are hardware keys like YubiKeys. You could replace your on-device SSH keys with a YubiKey for extra protection. It offers per-use confirmations which require you to touch the YubiKey briefly if a tool tries to read your SSH key. The downside of a physical device is obviously that if you lose it, you have to rotate your SSH keys, but this inconvenience buys you a lot more protection.

Whatever you choose: Please don't store your SSH keys in text files in ~/.ssh!

Conclusion

And that's it! I hope you enjoyed this article! If you want to support me, you can buy my book or video courses (one and two). Follow me on Bluesky or subscribe to my newsletter below if you want to get notified when I publish the next blog post. Until next time! Cheerio 👋

Liked this article? Sign up for more