Skip to content

2/18/2026

KeePassXC SSH agent: signing fails while authentication works

KeePassXC SSH agent: signing fails while authentication works

3 min read
ssh keepassxc git macos security

Problem: after configuring git to use SSH commit signing (gpg.format = ssh), ssh-keygen -Y sign fails with “agent refused operation” — yet SSH authentication to GitHub works fine. The key is visible in ssh-add -l, and “Require user confirmation” is unchecked in KeePassXC.

echo "test" | ssh-keygen -Y sign -n git -f <(ssh-add -L | grep my-key)
Signing data on standard input
Couldn't sign message (signer): agent refused operation
Signing (stdin) failed: agent refused operation

Why it happens

KeePassXC is a client, not an agent — it adds keys to whatever ssh-agent is running at SSH_AUTH_SOCK. When adding keys, it speaks the SSH agent protocol directly (not via ssh-add). The key detail is in SSHAgent.cpp:

request.write(
    (settings.useLifetimeConstraintWhenAdding() ||
     settings.useConfirmConstraintWhenAdding() || isSecurityKey)
    ? SSH_AGENTC_ADD_ID_CONSTRAINED   // code 25
    : SSH_AGENTC_ADD_IDENTITY);        // code 17

If either “Require user confirmation” or “Remove key from agent after X seconds” is checked, the key gets added with SSH_AGENTC_ADD_ID_CONSTRAINED. The confirm constraint triggers the agent to call confirm_key(), which invokes SSH_ASKPASS. macOS doesn’t ship ssh-askpass, so the confirmation silently fails and the agent returns SSH_AGENT_FAILURE.

SSH authentication still works because the ssh client has its own interactive TTY path that bypasses askpass. But ssh-keygen -Y sign goes straight through the agent’s askpass mechanism — so it fails.

The subtle part: ssh-add -l doesn’t show constraints. There’s no way to know a loaded key has the confirm flag just by listing it. And changing the checkbox in KeePassXC doesn’t retroactively update keys already in the agent — it only affects future addIdentity() calls.

Fix

# Remove all keys from the agent
ssh-add -D

# Lock and unlock the KeePassXC database
# (forces re-add with CURRENT settings)

# Verify signing works
ssh-add -l
echo "test" | ssh-keygen -Y sign -n git -f <(ssh-add -L | grep my-key)

Make sure both “Require user confirmation” and “Remove key from agent after X seconds” are unchecked in the entry’s SSH Agent tab.

Debugging

If the fix above doesn’t work, run the agent in debug mode to see exactly why it’s refusing:

kill $(lsof -t ~/.ssh/agent.sock)
ssh-agent -d -a ~/.ssh/agent.sock
# In another terminal, trigger the sign — watch the debug output

Notes

  • The same symptom appears over SSH agent forwarding (e.g., Tailscale SSH), making it easy to misdiagnose as a forwarding issue
  • macOS Sonoma 14.6+ broke SSH_ASKPASS inheritance in launchd, which can silently break previously working setups after an OS update
  • If you need the confirmation feature, install brew install theseal/ssh-askpass/ssh-askpass and set SSH_ASKPASS_REQUIRE=force