AIGC标识 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

三条可以带走的:

  1. 装了桌面版,不等于你终端里的 codex 也在转发。两边是两套安装。
  2. 要找这段逻辑,搜桌面版的 app.asar,不要只搜包里那份 codex.exe。
  3. 脚本在,不等于钥匙已经转出去。本机 agent 没开时,没有 socket 可挂。

同一台 Windows 上桌面版和 CLI 的对照

背景

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 操作;怎么利用这件事,本文不写。

清单

参考

posted @ 2026-11-09 18:41  SpectrAI光谱AI  阅读(13)  评论(0)    收藏  举报