SSH: CC_ENV_EXTRACT_LIST missing SSH_AUTH_SOCK breaks 1Password SSH agent

Status Open
Maintainer reply None cached
Activity 12 comments · opened Mar 1, 2026

Summary

Claude Code Desktop has two issues that break SSH connections for users of 1Password SSH agent (and likely other non-default SSH agents):

  1. SSH_AUTH_SOCK not imported from shell environment: The CC_ENV_EXTRACT_LIST whitelist in shellPathWorker.js does not include SSH_AUTH_SOCK. Claude Desktop always inherits the macOS default SSH agent socket (/private/tmp/com.apple.launchd.*/Listeners) instead of the user-configured agent.
  1. IdentityFile pointing to a .pub file crashes ssh2: 1Password's auto-generated SSH config sets IdentityFile to a .pub file (the agent handles the actual private key). Claude Desktop reads this file and passes it to ssh2 as privateKey, which throws "privateKey value does not contain a (valid) private key" instead of falling through to agent-based auth.

Steps to Reproduce

  1. Configure 1Password SSH agent (standard setup: SSH_AUTH_SOCK in shell profile + Include ~/.ssh/1Password/config + IdentityAgent in ~/.ssh/config)
  2. Verify ssh works from terminal
  3. Add an SSH connection in Claude Desktop
  4. Try to connect → fails with "privateKey value does not contain a (valid) private key" or falls back to password auth

Workaround

Both of the following are needed:

  1. In the SSH connection settings UI, set the Identity File field to none — this prevents ssh2 from reading the .pub file
  2. Launch Claude Desktop from terminal: SSH_AUTH_SOCK=~/.1password/agent.sock open -a Claude

Suggested Fix

  1. Add "SSH_AUTH_SOCK" to CC_ENV_EXTRACT_LIST in shellPathWorker.js
  2. When an IdentityFile fails to parse as a private key, skip it and fall through to agent auth instead of throwing

Environment

  • macOS Tahoe 26.3
  • Claude Desktop (latest as of 2026-02-28)
  • 1Password SSH agent

🤖 Generated with Claude Code

View original on GitHub ↗

11 Comments

github-actions[bot] · 6 months ago

Found 3 possible duplicate issues:

  1. https://github.com/anthropics/claude-code/issues/23535
  2. https://github.com/anthropics/claude-code/issues/14485
  3. https://github.com/anthropics/claude-code/issues/9719

This issue will be automatically closed as a duplicate in 3 days.

  • If your issue is a duplicate, please close it and 👍 the existing issue instead
  • To prevent auto-closure, add a comment or 👎 this comment

🤖 Generated with Claude Code

jvkamp · 6 months ago

Not a duplicate of the linked issues. Those are about plugin marketplace git clone operations failing with 1Password. This issue is specifically about SSH remote connections (connecting to remote hosts via Claude Desktop) failing due to two distinct bugs:

  1. SSH_AUTH_SOCK not being imported from the user's shell environment (CC_ENV_EXTRACT_LIST in shellPathWorker.js)
  2. ssh2 throwing on .pub IdentityFile instead of falling through to agent auth

Different feature, different code paths, different workarounds.

🤖 Generated with Claude Code

xXMrNidaXx · 6 months ago

Analysis:

The 1Password SSH agent integration issue has two distinct failure modes that need separate fixes:

Issue 1: SSH_AUTH_SOCK Import

The environment variable whitelist in shellPathWorker.js is too restrictive. Besides SSH_AUTH_SOCK, there are other agent-related variables that should probably be considered:

  • SSH_AUTH_SOCK (primary)
  • SSH_AGENT_PID (for spawned ssh-agent processes)
  • SSH_CONNECTION / SSH_TTY (for nested sessions)
  • GPG_AGENT_INFO (for GPG agent forwarding)

A broader fix might be to allow SSH_* prefix variables, with an explicit denylist for security-sensitive ones like SSH_ASKPASS if there's concern about prompt hijacking.

Issue 2: IdentityFile Parsing

The ssh2 library's key parsing fails hard when encountering a .pub file. The fix should:

  1. Check file content first — if it starts with ssh-rsa, ssh-ed25519, etc., it's a public key
  2. Skip gracefully — log a debug message and continue to agent auth
  3. Support none keyword — the workaround suggests this already works in the UI
// Pseudo-fix for parsePrivateKey
if (keyContent.match(/^ssh-(rsa|ed25519|ecdsa)/)) {
  console.debug("Skipping public key file, falling through to agent");
  return null; // Let agent auth handle it
}

The workaround of launching from terminal with SSH_AUTH_SOCK explicitly set confirms the socket path resolution is the core issue — once that's fixed, the IdentityFile issue becomes secondary (agent auth would succeed before file parsing is attempted).

ryantology · 5 months ago

This has been marked as stale but it is a pretty important workflow issue.

jamie-tm · 5 months ago

This issue is a blocker for me, as my dev environment is a remote server and my SSH keys live in 1Password. I'd love to be able to use Claude Desktop locally, so I have the friendlier UI.

For context: I'm running Windows 11 locally and Ubuntu 24 remotely.

bdelamarre · 5 months ago

I think this is a pretty important feature as storing private key on filesystem is a risk and many people should migrate to storing their private keys to secure places

ideali · 5 months ago

Adding another data point — this is also a blocker for me.

Setup: macOS, 1Password SSH Agent, server with publickey-only auth.

What I found debugging from Claude Code CLI:

  • ssh-add -l inside Claude Code sandbox → Error connecting to agent: Operation not permitted (sandbox blocks Unix socket access)
  • ssh-add -l with sandbox disabled → keys from 1Password are visible and SSH works fine
  • Claude Desktop's SSH Remote shows password prompt → enters password → "All configured authentication methods failed" (server doesn't accept passwords, only publickey)

Root cause confirmed: Desktop's ssh2 library never reaches the 1Password agent socket. The IdentityAgent directive in ~/.ssh/config is ignored, and SSH_AUTH_SOCK is not passed through.

Impact: Users who follow security best practices (keys in 1Password, no private key files on disk) cannot use SSH Remote at all. The workaround of launching from terminal with SSH_AUTH_SOCK doesn't reliably work either, since open -a goes through LaunchServices.

This has been open for a month with no assignee. Would appreciate if someone from the team could pick this up — it's a two-line fix for the env var whitelist, and a small try/catch for the .pub file parsing.

radialmonster · 4 months ago

Trying to day with the new claude desktop for windows, I use Bitwarden desktop for my ssh key stores. Using windows ssh and python ssh whenever I connect my bitwarden pops up and asks me to authorize the connection using the key saved in my bitwarden. Claude Desktop does not trigger this same result, and just fails the ssh connection.

thx

Claude itself investigated and here is what it says:

Same root cause on Windows + Bitwarden SSH agent (not macOS, not 1Password), which suggests this is cross-platform in the ssh2 client layer, not specific to CC_ENV_EXTRACT_LIST.

Environment

  • Windows 11 (10.0.26200)
  • Claude Desktop 1.2581.0.0 (MSIX: Claude_1.2581.0.0_x64__pzs8sxrjxfjjc)
  • Bitwarden Desktop SSH agent serving \\.\pipe\openssh-ssh-agent
  • Windows OpenSSH Authentication Agent service stopped + disabled (Bitwarden owns the pipe)

Proof from %APPDATA%\Claude\logs\ssh.log:
[SSH2Connection] Resolved root@host -> root@host:22 (identityFiles: 7)
[SSH2Connection] Connecting to root@host:22 (agent: false, key: false, proxy: false, keyboard: true)
[SSH2Connection] Connection error: All configured authentication methods failed

Note agent: false — Claude Desktop never queries the agent pipe, so Bitwarden never fires its approval popup.
Comparison — at the same moment, system ssh.exe (OpenSSH_for_Windows_9.5p2) against the same host authenticates fine via Bitwarden:
debug1: get_agent_identities: agent returned 3 keys
debug1: Will attempt key: <keyname> ED25519 ... agent
debug1: Offering public key: <keyname> ED25519 ... agent
debug1: Server accepts key: <keyname> ED25519 ... agent
Authenticated to host ([x.x.x.x]:22) using "publickey".

Windows-specific fix note: alongside SSH_AUTH_SOCK on macOS/Linux, the Windows agent uses a named pipe at \\.\pipe\openssh-ssh-agent (same path regardless of which agent implementation owns it — Windows OpenSSH, Bitwarden, 1Password, etc.). When wiring ssh2's agent option, use that pipe path on win32:

const agent = process.platform === 'win32'
? '\\.\pipe\openssh-ssh-agent'
: process.env.SSH_AUTH_SOCK;
david-menday · 4 months ago

I closed #46273 (SSH_AUTH_SOCK passthrough) as a duplicate of this, but I'm a bit worried the enterprise angle is getting overlooked.

The same fix (SSH_AUTH_SOCK in CC_ENV_EXTRACT_LIST, skip unparseable IdentityFile entries) also unblocks PKCS#11 hardware tokens (YubiKey PIV, PIV/CAC smart cards) and FIDO sk-* keys when loaded into ssh-agent — direct PKCS#11 use without an agent (PKCS11Provider in ~/.ssh/config) would need the OS ssh path. For enterprises whose key-custody policy prohibits software-held private keys, Claude Desktop's SSH dialog is a compliance blocker.

Longer-term, driving the OS ssh binary would inherit OpenSSH's full config surface (agent forwarding, PKCS11Provider, IdentityAgent, ProxyCommand, Match, GSSAPI, etc.) — though I realize that's a bigger change than the one above.

Happy to reopen/reformulate #46273 if you'd rather track it separately.

rjlg · 4 months ago

Adding a deeper diagnosis for bug #2 in @jvkamp's split (ssh2 rejecting .pub IdentityFiles instead of falling through to agent auth) — filed separately as #53502 then realised it's covered here. Closing that one; pasting the extra detail in case it helps whoever picks this up.

Why the wrapper rejects .pub stubs

The bundled per-identity loader returns the raw file bytes to be used as privateKey:

async function t4e(e) {
  const A = await fs.readFile(expand(e));
  if (!A) return;
  const t = ssh2.utils.parseKey(A);
  if (t instanceof Error) return;            // skips on parse error
  return A;                                  // returns raw buffer
}
// ...
a.push({ path: Q, buffer: h });
a.length > 0 && (r.privateKey = a[0].buffer);

.pub stubs parse fine (valid public keys), so the guard doesn't fire. They then hit ssh2.Client.connect:

if (parsedKey.getPrivatePEM() === null)
    throw new Error("privateKey value does not contain a (valid) private key");

The thrown string is not "authentication methods failed", so the surrounding fallback loop short-circuits and the agent path is never tried — even if SSH_AUTH_SOCK is set correctly.

The "works on host A, fails on host B" asymmetry

ssh -G resolution is cached in an in-memory Map for the lifetime of the Claude Code process. Whether a host hits the bug depends on whether its IdentityFile existed on disk at first-resolution time:

  • File missing → fs.readFile fails → t4e returns undefined → identity-files array empty → agent gate !(identitiesOnly && !hasFiles) is truthy → agent auth succeeds.
  • File present (the normal 1Password case) → buggy path fires → connect fails.

Restarting Claude Code can flip a previously-working host into a broken state, which makes this confusing to diagnose in the wild.

Suggested one-line fix in t4e

const parsed = ssh2.utils.parseKey(A);
if (parsed instanceof Error) return;
if (parsed.getPrivatePEM && parsed.getPrivatePEM() === null) {
  // log: "Skipping identity file <path>: public key only"
  return;
}
return A;

That makes 1Password's .pub-stub layout (and any other agent-only setup) Just Work without the IdentitiesOnly no + IdentityFile none workaround on every host.

Current two-part workaround (both halves required)

  1. Pre-Include block in ~/.ssh/config:

``
Host <affected-hosts>
IdentitiesOnly no
``

  1. Per-host IdentityFile none at the bottom of each affected Host block (resets the identity-files list — ssh -G honours none, and the wrapper's parser does too).

Clearing the file list alone disables the agent gate; clearing IdentitiesOnly alone still runs the buggy public-key-as-privateKey path.

Environment

  • macOS 26.4.1, Claude Code 2.1.119
  • 1Password 8 SSH agent with Match Host rules pinning per-host ed25519 keys exposed as ~/.ssh/1Password/SHA256_<hash>.pub
nzoschke · 3 months ago

@rjlg's two part workaround worked for me, plus a tweak to ~/.config/1Password/ssh/agent.toml to present a specific key of many first

# explicitly present a specific key first for Claude Desktop
[[ssh-keys]]
item = "personal"

# All 1Password keys in alphabetical order
[[ssh-keys]]
vault = "Private"
...

You can see the list of keys with SSH_AUTH_SOCK="$HOME/Library/Group Containers/2BUA8C4S2C.com.1password/t/agent.sock" ssh-add -L

Showing cached comments. Read the full discussion on GitHub ↗