Codex 桌面版会挂 SSH agent,CLI 0.163.0 不会
Hacker News 今天有一条 17 分的帖子,标题是「ChatGPT 桌面版把你的 SSH agent 转到远程机器」。帖子说远程上的 agent 能用你本机的钥匙,比如推你的私有仓库,证据给的是 PR #28131 的一条评论。
我没有连任何远程,也没有启动 ssh-agent,更没有列钥匙。只在这台 Windows 上做了只读对照:桌面版安装包里的启动脚本、npm 装的 CLI、本机 agent 服务的状态。对照下来,HN 的标题把两件事写成了一件。桌面版 26.1013.3656.0 的界面包里确实有「把 SSH_AUTH_SOCK 挂到固定路径」的脚本;我正在用的 CLI 0.163.0 没有这个开关。而这台机器的 ssh-agent 是停的,脚本在,没有可转出去的 agent。
先说结论
| 看哪里 | 这台机器上的结果 |
|---|---|
桌面版 app.asar |
有固定路径 forwarded-ssh-agent.sock,条件成立就 ln -sfn |
桌面版自带的 codex.exe |
搜不到这段字符串 |
| npm CLI 0.163.0 | app-server proxy --help 只有 --sock,没有 --forward-ssh-agent |
本机 ssh-agent |
Stopped,启动类型 Disabled |
三条可以带走的:
- 装了桌面版,不等于你终端里的
codex也在转发。两边是两套安装。 - 要找这段逻辑,搜桌面版的
app.asar,不要只搜包里那份codex.exe。 - 脚本在,不等于钥匙已经转出去。本机 agent 没开时,没有 socket 可挂。

背景
HN 帖子的「证据」是 OpenAI 员工 abhinav-oai 在 PR 里回审稿机器人的一句话,原文是:
Codex app will launch the app server with the following so we should be good
SSH_AUTH_SOCK=~/.codex/app-server-control/forwarded-ssh-agent.sock \
nohup codex app-server --listen unix://
这条 PR 的状态不是已合并。PR #28131 标题是 Refresh SSH agent for app-server proxy,作者自己写的是给 codex app-server proxy 加一个可选的 --forward-ssh-agent:proxy 先检查继承到的 agent socket,再原子更新旁边那个固定软链接;自己没有可用 agent 时不动已有链接。它标了 Fixes #22567。页面上是 Closed with unmerged commits,github-actions 的关闭理由是超过 14 天没有更新。
#22567 讲的是另一头:远程 app-server 是长期进程,记下的是启动它的那次 SSH 的 SSH_AUTH_SOCK,会话结束后 socket 被删掉,后面的 docker buildx build --ssh 还拿着这个死路径。issue 现在标成 completed 关了,但挂在 Development 里的仍是这条没合并的 PR。关了不等于这段代码进了你机器上的 CLI。
今天真正对得上现网行为的是还开着的 #59694。报告人的桌面版是 26.1023.6123.0,Windows 和 macOS 两个桌面客户端连同一个远程账号时,后连上的那个会换掉共享软链接;他静态看过 26.1027.3384.0,说选择逻辑也在,但那一包没有跑过。他贴出的脚本只判断路径是不是 socket,不判断 socket 能不能应答。issue 里写明:#28131 关了且没合并,不能拿来当已发布的修复。
实测
环境是 Windows 10。codex doctor 写明桌面版已安装、当前没在运行。版本是两条命令各自的输出,不是帖子里的版本。
$ codex --version
codex-cli 0.163.0
Notes
↑ updates 0.167.0 available (current 0.163.0)
↑ desktop build 26.1103.4239.0 available
Desktop App
✓ desktop the desktop application is installed
version 26.1013.3656.0
running false
Name : OpenAI.Codex
Version : 26.1013.3656.0
InstallLocation : C:\Program Files\WindowsApps\OpenAI.Codex_26.1013.3656.0_x64__2p2nqsd0c76g0
桌面版 app\resources\app.asar 有 582,042,823 字节。字符串只出现一次,不在包内那份 341,312,816 字节的 codex.exe 里。npm 全局装的 CLI 在另一条路径,bin\codex.exe 341,270,320 字节,同样没有这些字符串:
app.asar forwarded-ssh-agent.sock 1 处
app.asar --forward-ssh-agent 0
桌面版 codex.exe forwarded-ssh-agent.sock 0
桌面版 codex.exe SSH_AUTH_SOCK 0
npm 0.163.0 的 bin\codex.exe forwarded-ssh-agent.sock 0
npm 0.163.0 的 bin\codex.exe --forward-ssh-agent 0
npm 0.163.0 的 bin\codex.exe SSH_AUTH_SOCK 0
app.asar 里这段不是一整段 shell,是几段字符串拼出来的。路径变量和链接命令是:
g6 = "${CODEX_HOME:-$HOME/.codex}/app-server-control/forwarded-ssh-agent.sock"
_6 = if [ -S "${SSH_AUTH_SOCK:-}" ]; then
ln -sfn -- "$SSH_AUTH_SOCK" <g6>
elif [ ! -S <g6> ]; then
rm -f -- <g6>
fi
远程拉起 app-server 的那条,拼完是:先建目录,再执行上面的 _6,然后带上固定路径启动。
SSH_AUTH_SOCK=<g6> nohup <远程 codex> -c features.code_mode_host=true \
app-server --listen unix:// </dev/null >${日志} 2>&1 &
同一次连接里,桌面版随后执行的 proxy 命令是「先跑 _6,再 exec codex app-server proxy」。这里没有 --forward-ssh-agent。转发是桌面版自己在 shell 里做的,不是 CLI 的一个开关。
CLI 帮助对得上这次字符串扫描:
$ codex app-server proxy --help
Proxy stdio bytes to the running app-server control socket
Options:
--sock <SOCKET_PATH>
Path to the app-server Unix domain socket to connect to
--enable <FEATURE>
--disable <FEATURE>
-h, --help
只有 --sock。codex app-server --help 的子命令是 daemon、proxy、generate-ts、generate-json-schema,也没有转发相关的项。
本机服务和配置:
Name : ssh-agent
Status : Stopped
StartType : Disabled
~/.ssh/config 不存在。当前 shell 没有 SSH_AUTH_SOCK。~/.codex/app-server-control 这个目录也不存在,所以本机用户目录下没有那个固定 socket。这次是让 SpectrAI 里的 Agent 在本机把 app.asar 和两份 codex.exe 逐段对照的,命令和输出都留在会话记录里。
深入
和 #59694 贴出来的脚本比,选择逻辑一致:当前连接自己有 socket 就覆盖固定软链接;固定路径已经是 socket 时,这次连接即使没有 agent 也不删它。差别是他贴的是展开后的 shell,我这台 26.1013.3656.0 里是 JS 字符串拼接,另外多了启动前的 umask 077、写日志,以及按当前用户 pkill 匹配旧进程。他报告的是 26.1023,比这台新;更旧的这一包里脚本已经在了。
这和被当成证据的那条 PR 不是同一条实现。PR 想加的是 CLI 开关,而且写了「没有可用 agent 就不要动别人的链接」。桌面版没有走这个开关,它每次建 proxy 都先跑 _6。-S 只表示「看起来像 socket」,不表示对面还能应答。#59694 里 Mac 那边的 socket 没应答、Windows 那边的还活着,共享链接却被换成了不能用的那个,和这种判断方式对得上。我没有两台客户端,这条没有复现。
另一个容易看错的地方:同一份 app.asar 里,Cloud 连接用的 ssh 参数写了 ForwardAgent=no。那是另一条连接路径。远程 SSH 这段没有这个参数,不能拿 Cloud 的配置推断远程会话不会转发。
#22567 的评论里有人贴了提示词,让模型在 Git 认证失败后自己去找 proxy 进程、改软链接。那段我不重复。它恰好说明:固定路径是给远程会话用的,谁最后改成功,后面的命令就用谁的 agent。
暂时做不了怎么办
这次证明的是「安装包里有这段脚本」和「这台 CLI 没有那个开关」,不是「我连上远程后用本机钥匙推成了」。要验证后半句,得另备一台自己的机器,先把本机 agent 开起来,再看远程那个固定路径指到哪。我没有做这一步。
按脚本本身的分支,这次连接的 SSH_AUTH_SOCK 不是 socket 时,它不会新建转发;固定路径如果还不是 socket,它会把残留文件删掉。这台 Windows 的 OpenSSH agent 是 Disabled,当前没有 SSH_AUTH_SOCK。在这个状态下,桌面版即使用这段脚本去连远程,也没有本机 Windows agent 可以挂上去。Pageant 或其他钥匙来源这次没测,不能一起算进去。
CLI 这边只查了 0.163.0。npm view @openai/codex version 是 0.167.0,codex doctor 也提示可以升到 0.167.0、桌面版可以到 26.1103.4239.0。我没有升级,所以不能说新版 CLI 依然没有这个开关,只能说现在这条 PATH 上的没有。
安全类的题我不投 CSDN。远程上一旦真的挂上了本机 agent,影响就是远程会话能做本机钥匙能做的 Git 操作;怎么利用这件事,本文不写。
清单
参考
- HN 原帖:https://news.ycombinator.com/item?id=50422628
- 现网行为(仍 Open):https://github.com/openai/codex/issues/59694
- 未合并就关闭的 PR:https://github.com/openai/codex/pull/28131
- HN 当证据的那条评论:https://github.com/openai/codex/pull/28131#discussion_r3410013180
- 远程 app-server 拿着过期 socket:https://github.com/openai/codex/issues/22567
浙公网安备 33010602011771号