🩹🩹 Codex App Remote SSH does not honor ForwardAgent from ~/.ssh/config, breaking docker buildx --ssh

Resolved 💬 3 comments Opened May 13, 2026 by okhomenko Closed Jul 30, 2026

What version of the Codex App are you using (From "About Codex" dialog)?

26.506.31421 (2620)

Bundled/local CLI observed:

codex-cli 0.130.0

What subscription do you have?

TODO: fill in subscription

What platform is your computer?

Local client:

Darwin 25.4.0 arm64 arm
macOS 26.4.1
OpenSSH_10.2p1, LibreSSL 3.3.6
docker buildx v0.33.0

Remote host:

TODO: fill in remote OS / uname -mprs

What issue are you seeing?

Codex App's Remote SSH feature appears to discover hosts from ~/.ssh/config, but the actual remote connection does not behave like normal OpenSSH for agent forwarding.

My normal terminal SSH connection honors this host's ForwardAgent yes configuration. When I connect manually with the same SSH host alias, the remote shell gets a usable forwarded SSH agent socket and private Git SSH access works.

Inside a Codex App Remote SSH project on the same host, the remote environment either does not have a usable forwarded agent or has an invalid/stale SSH_AUTH_SOCK. This breaks Docker BuildKit / buildx workflows that depend on SSH agent forwarding, for example builds using:

docker buildx build --ssh default ...

The failure happens before the useful build step because BuildKit is handed an unusable SSH agent socket. In one run, the start command failed before building because SSH_AUTH_SOCK pointed at a deleted socket.

This looks like Codex Remote SSH is not fully honoring the selected host's OpenSSH config, specifically ForwardAgent yes, or is preserving/exporting a stale SSH_AUTH_SOCK into the remote app-server/session environment.

What steps can reproduce the bug?

  1. Configure an SSH host alias in ~/.ssh/config with agent forwarding enabled:

``sshconfig
Host my-devbox
HostName <remote-host>
User <user>
ForwardAgent yes
``

  1. Confirm normal terminal SSH honors the config:

``sh
ssh my-devbox 'echo "SSH_AUTH_SOCK=$SSH_AUTH_SOCK"; test -S "$SSH_AUTH_SOCK" && echo socket-exists; ssh-add -l'
``

Expected control result: SSH_AUTH_SOCK points at a live remote forwarded-agent socket, and ssh-add -l can list the local agent identities.

  1. Open Codex App.
  2. Use the Remote SSH feature to connect to the same my-devbox host alias and open a remote project.
  3. In the Codex remote shell/tool environment, run:

``sh
echo "SSH_AUTH_SOCK=$SSH_AUTH_SOCK"
test -S "$SSH_AUTH_SOCK" && echo socket-exists || echo socket-missing
ssh-add -l
``

Actual result: SSH_AUTH_SOCK is missing, points to a deleted/nonexistent socket, or ssh-add -l cannot see the forwarded identities.

  1. Try a BuildKit/buildx build that needs SSH during the build, for example a Dockerfile using a private Git dependency and:

``sh
docker buildx build --ssh default="$SSH_AUTH_SOCK" .
``

Actual result: the build fails because the SSH agent socket is not usable from the Codex remote session.

What is the expected behavior?

Codex App Remote SSH should honor OpenSSH config behavior for the selected host alias, including ForwardAgent yes, the same way a normal terminal ssh my-devbox invocation does.

At minimum:

  • if ForwardAgent yes is configured and a local agent is available, the Codex remote session should get a live forwarded SSH_AUTH_SOCK;
  • ssh-add -l in the Codex remote session should behave like ssh my-devbox 'ssh-add -l';
  • Docker BuildKit/buildx SSH mounts should work with docker buildx build --ssh default ...;
  • if agent forwarding is unsupported or unavailable, Codex should not export a stale/deleted SSH_AUTH_SOCK; it should leave it unset or show a clear diagnostic.

Additional information

Related issues that seem adjacent but do not cover this exact failure:

  • openai/codex#18301: Codex App Remote SSH uses id_rsa by default even if it doesn't exist. This suggests Remote SSH identity/config behavior differs from normal OpenSSH.
  • openai/codex#18322: Codex Remote SSH fails if RemoteCommand is included in SSH config. This is another SSH config parity issue.
  • openai/codex#18819: SSH connect timeout configurable; asks Codex Desktop to respect ~/.ssh/config where possible or expose equivalent settings.
  • openai/codex#20128: Codex App Remote SSH behaves differently from normal ssh <alias>/VS Code Remote SSH in a remote setup.

The issue is not that Codex fails to discover ~/.ssh/config hosts entirely. The host is visible/usable in Codex Remote SSH. The problem is that the connection/session does not appear to preserve the full OpenSSH behavior needed for agent forwarding.

View original on GitHub ↗

3 Comments

okhomenko · 3 months ago

Additional findings from inspecting the live Codex Mac App remote session:

This looks less like OpenSSH ignoring ForwardAgent, and more like the remote Codex app-server is long-lived and keeps the SSH_AUTH_SOCK value from the SSH session that originally launched it.

Observed runtime path from the Codex Mac App process tree:

/Applications/Codex.app/Contents/MacOS/Codex
  -> /Applications/Codex.app/Contents/Resources/codex app-server --analytics-default-enabled
  -> ssh -T -v ... <ssh-host> ... codex app-server proxy

On the remote host, the proxy talks to an existing Unix socket owned by a detached app-server:

~/.codex/app-server-control/app-server-control.sock

codex app-server proxy
  -> ~/.codex/app-server-control/app-server-control.sock
  -> long-lived codex app-server --listen unix://

Control checks:

ssh -G <host> | grep -i '^forwardagent '
# forwardagent yes

ssh <host> 'echo "$SSH_AUTH_SOCK"; test -S "$SSH_AUTH_SOCK" && echo socket-exists; ssh-add -l'
# remote forwarded socket exists
# ssh-add -l lists local identities

But the long-running remote app-server process had an old SSH_AUTH_SOCK in /proc/<pid>/environ, and that socket no longer existed:

remote codex app-server --listen unix://
  SSH_AUTH_SOCK=/home/<user>/.ssh/agent/s.<...>.sshd.<old-id>
  test -S "$SSH_AUTH_SOCK" -> false

Meanwhile, the current codex app-server proxy processes spawned by the Mac App SSH connection had different, live forwarded-agent sockets:

remote codex app-server proxy
  SSH_AUTH_SOCK=/home/<user>/.ssh/agent/s.<...>.sshd.<current-id>
  test -S "$SSH_AUTH_SOCK" -> true

So the likely failure mode is:

  1. Codex Mac App connects over SSH with agent forwarding enabled.
  2. The remote bootstrap starts codex app-server --listen unix:// detached, inheriting that SSH session's SSH_AUTH_SOCK.
  3. That SSH session ends, so the forwarded-agent socket is removed.
  4. Later Mac App connections start fresh codex app-server proxy processes with live forwarded sockets, but actual remote tool/shell execution happens inside the already-running app-server process, whose environment still points at the dead socket.
  5. docker buildx build --ssh default... fails because the app-server process exports or inherits the stale SSH_AUTH_SOCK.

This also explains why direct terminal SSH works while Codex remote tools fail in the same host alias.

Possible fix directions:

  • Do not let the detached remote app-server preserve a stale SSH_AUTH_SOCK from its bootstrap session.
  • When connecting through codex app-server proxy, propagate the current proxy connection's live agent socket to command execution sessions, or refresh app-server environment state.
  • If that is not supported, unset invalid SSH_AUTH_SOCK before running tools so BuildKit does not receive a deleted socket.
  • Detect SSH_AUTH_SOCK pointing at a non-socket and emit a diagnostic.

Relevant public code path that appears related to detached app-server startup: https://github.com/openai/codex/blob/main/codex-rs/app-server-daemon/src/backend/pid.rs

zhou13 · 2 months ago

Thank you for the investigation. I add the following to my codex prompt to workaround this issue until it is fixed:

If a Git SSH operation fails with a GitHub public-key/authentication error,
  check whether `$SSH_AUTH_SOCK` exists and is a live socket. If it is stale,
  find the most recent `codex app-server proxy` process, read its
  `SSH_AUTH_SOCK` from `/proc/<pid>/environ`, verify it with `ssh-add -l`, and
  softlink the current stale `$SSH_AUTH_SOCK` path to the proxy socket before
  retrying the Git operation.
bsdayo · 2 months ago
Thank you for the investigation. I add the following to my codex prompt to workaround this issue until it is fixed: `` If a Git SSH operation fails with a GitHub public-key/authentication error, check whether $SSH_AUTH_SOCK exists and is a live socket. If it is stale, find the most recent codex app-server proxy process, read its SSH_AUTH_SOCK from /proc/<pid>/environ, verify it with ssh-add -l, and softlink the current stale $SSH_AUTH_SOCK path to the proxy socket before retrying the Git operation. ``

Works perfectly, thanks!
Hope this issue gets fixed soon.