An SSH agent provides signing operations for public-key authentication. For ordinary software keys, loading an encrypted private key unlocks material that the agent can then use without asking for the file passphrase on every connection. Clients receive public identities and signatures, not an exported private key through the normal agent protocol. Hardware-backed identities are different: the authenticator can retain the private key and require touch or verification.

The socket provides access to a service

OpenSSH normally discovers the agent through SSH_AUTH_SOCK, but IdentityAgent in client configuration can select a different socket or disable agent use. Knowing a pathname is not equivalent to having permission to connect. Socket and parent-directory permissions matter, while root and other processes running as the same user are important threats. Do not treat an environment variable itself as a secret that can replace operating-system isolation.

Agent access is also not an unconditional promise that every signing request succeeds. Key constraints, confirmation requirements, hardware presence, and protocol restrictions can refuse requests. Even a successful signature does not force a remote server to accept that key or grant access. Separate local signing capability from the server’s authorization decision.

Bound both the key and the delegation

ssh-add loads an identity, asking for its passphrase when needed. Other configured paths, such as AddKeysToAgent in ssh, can also load identities; ssh-add is not the only possible unlock path. The agent avoids repeatedly reading the encrypted key file, but does not guarantee that every copy of private material is absent from swap, dumps, backups, or other processes.

The -t option assigns a lifetime to an added identity. When that lifetime expires, the identity is removed; the option is not merely a reminder. The agent can supply a default lifetime; without either limit, an ordinary identity can remain until removed or the agent exits. Removing or replacing the disk file does not automatically replace a previously loaded copy.

The -c option requires confirmation through ssh-askpass. It is the helper’s successful exit status that approves use; a missing terminal on the remote host is not the determining test. Verify the local confirmation mechanism and reject unexpected requests. Confirmation reduces unattended use but does not replace understanding which host or operation a prompt represents.

Destination constraints, introduced in OpenSSH 8.9, further restrict allowed authentication paths using host keys. Forwarded use needs supporting clients and servers plus correct known-host data. A hostile hop can relay the socket again outside cooperating SSH, but signing remains limited to permitted destinations. These constraints are not a firewall; verify compatibility and keep OpenSSH patched.

When it breaks

Agent forwarding lets a remote host relay signing requests while the forwarding channel exists. An administrator or compromised process there may use that capability without extracting the private key. Prefer avoiding forwarding when it is unnecessary, and review the effective client configuration rather than assuming that omitting -A proves it is disabled.

Deleting an identity from the agent does not revoke a stolen private-key copy, remove a server’s authorized_keys entry, or necessarily terminate an already established SSH session. Conversely, removing server authorization can stop new logins while the agent still holds the key. A recovery plan must address each affected copy, authorization record, and active session separately.

Modern OpenSSH agents restrict remote provider loading and certain FIDO signatures; identifying remote clients relies on cooperating SSH forwarding. These safeguards reduce specific misuse, including using forwarded authenticators outside SSH. They are not a reason to expose the socket broadly or enable relaxed options without a reviewed need. Defaults and socket locations can vary across versions and platform integrations.

Software-agent and hardware-authenticator storage panels feed a protected signing-service explanation; server authorization, signing constraints and explicit-versus-none IdentityAgent configuration remain separate.
Socket access can delegate signing while private-key storage and server authorization remain separate. The retained fixture checks configuration selection only.

Check it quickly

Save as agent_config.py and run python3 agent_config.py with OpenSSH installed. The fixture creates a temporary configuration and evaluates it using ssh -G. It neither starts an agent nor reads a private key, opens a connection, changes an existing agent, or depends on a real socket. Its synthetic socket differs from the configuration. No example ran in this source review.

import os
from pathlib import Path
import subprocess
import tempfile

with tempfile.TemporaryDirectory(prefix='agent-config-') as directory:
    work = Path(directory)
    alternate = str(work / 'alternate.sock')
    config = work / 'config'
    config.write_text(f'''Host chosen-agent
  HostName example.invalid
  IdentityAgent {alternate}
Host no-agent
  HostName example.invalid
  IdentityAgent none
''')
    env = {'PATH': os.defpath, 'SSH_AUTH_SOCK': str(work / 'environment.sock')}
    for host, expected in [('chosen-agent', alternate), ('no-agent', 'none')]:
        result = subprocess.run(['ssh', '-G', '-F', str(config), host],
                                env=env, cwd=work, text=True, capture_output=True, check=True)
        fields = dict(line.split(' ', 1) for line in result.stdout.splitlines())
        if fields.get('identityagent') != expected:
            raise RuntimeError('unexpected IdentityAgent')
        print(host, 'identityagent=', fields['identityagent'])
    if (work / 'alternate.sock').exists() or (work / 'environment.sock').exists():
        raise RuntimeError('the fixture must not create an agent socket')
    print('PASS: explicit socket overrides environment; none disables agent use')

The first result selects the explicit alternate socket despite SSH_AUTH_SOCK. The second selects none. PASS confirms these configuration expectations only: ssh -G does not test socket access, signing, expiry, confirmation, or remote authentication. IdentityAgent none disables agent use for that invocation; it does not disable authentication using files or other mechanisms.

In a separate authorized test session, inspect loaded fingerprints and test lifetime and confirmation with a disposable identity. Do not run ssh-add -D against a shared everyday agent merely to reproduce an article: it removes all loaded identities and can interrupt other work. Keep the observation exercise separate from changes to credentials or live sessions.

Sources

  • OpenBSD: ssh-agent, signing service, socket access, provider and FIDO restrictions, checked 2026-10-15.
  • OpenBSD: ssh-add, lifetime, confirmation, removal, and destination constraints, checked 2026-10-15.
  • OpenBSD: ssh_config, IdentityAgent, AddKeysToAgent, and forwarding configuration, checked 2026-10-15.
  • OpenSSH: agent restriction, host-key binding and forwarding compatibility, checked 2026-10-15.