Repository navigation
Fix native reader permissions during benchmark CLI activation - #8530
Conversation
The copied native store was nested under a root-owned directory. Provision that directory for the exact unprivileged reader before copying the allowlisted files so Codex can initialize its local state. Preserve source isolation, credential exclusion and failed-read refusal. Signed-off-by: LoopX Agent <337587101+loopx-agent@users.noreply.github.com>
loopx-agent
left a comment
There was a problem hiding this comment.
Approval conclusion (author-owned PR; GitHub blocks formal self-approval)
Reviewer: model_agent · gpt-6.1-sol · OpenAI · runtime_reported · max
评审提交:c685e09b7e0cbb786537ce75a5d3145af3417741
动机 / Motivation
受影响的是用现有 benchmark CLI 激活流程核验原生会话的操作者。同一份 SQLite 副本读得出原内容,但主干的 observer 把 Codex home 建成 root 所有,非 root 读取器写不了初始化文件。候选先按实际读取 UID/GID 准备私有目录,再复制获准的成员。同一镜像和数据的真实 Docker 对照中,主干返回 PermissionError,候选以 65534:65534、0700 初始化成功并读回 0600 的 SQLite 文件。只修隔离读取器的目录权限。真实 Codex 启动、活跃容器的切换、安装采用和评分另行验收。
改动思路 / Approach
由现有 observer 在自己的容器里查询实际读取身份,再准备一个私有目录;源容器和权限判定留给原 owner。本次只修隔离读回的初始化权限,保留暂停、源证据、复制范围和原有失败路径。 我在同一镜像上分别运行主干和候选的真实 PausedSourceProbe,替换的只是 guest 读回程序,Docker 传输、文件权限和 SQLite 都是真实的。
具体改动 / Changes
关键代码讲解
_prepare_observer_native_home 以既有读取用户查询实际 euid/egid,验证目标是物理目录,再由 observer 内的 root 设置 owner 和 0700。PausedSourceProbe.__call__ 在复制已声明的状态文件前调用它。准备失败仍返回 unavailable;原流程删除 observer 并保留源 witness。两文件 +62/-2。准备目录;调用与失败路径。
规范依据:docs/reference/protocols/host-cli-source-activation-v0.md @ d3ac3bd8d69821ae5843b7cef5fdb6dcbc7cae74。private-reader-root 用真实 UID/GID 和 0600 SQLite 覆盖,source-untouched-refusal 用符号链接及清理检查覆盖,explicit-activation-unchanged 用 preview、Stop 和传输恢复覆盖。
对主干的风险 / Risks
未发现这次改动的阻塞问题。隔离读回没有复制合成的 auth 标记,源 witness 前后一致。符号链接场景拒绝后未复制文件,链接目标及原容器均未变化,observer 已删除。主干 21 项和候选 22 项隔离 Docker 测试、29 项 typed activation 测试通过。
语义与 CI 对齐
本地 premerge 的 5 项直接、6 项定向检查以及 Ruff、mypy 通过。发布前主干更新到 b89a574b05a3e7d5920a8e7184476dfb7b041790,只改仪表盘及浏览器测试。我在新主干复现了同一个权限失败,合并树无冲突。TypeScript digest 的 2 项、Python digest 的 1 项和两个 native Steward fixture 测试在主干与候选同因失败,Change Quality 未通过。benchmark 目录仍需维护者复核。未查询远程 CI。
我的整体评价 / Verdict
赞成这个隔离目录权限修复。它恢复了原本有效的本地读回,保留源证据和现行激活权限。交付面是既有 Docker 激活适配器的隔离读回,没有界面变更。独立验证用了真实 Docker、真实 UID/GID 与 SQLite,guest 读取程序是合成的;未在活动 benchmark 上运行真实 Codex 或切换 launcher。
English verdict: APPROVE. Provision the disposable native reader home for its actual UID/GID; the matched Docker probe recovers initialization and fails closed on a symlink. Merge validation remains held.
songoow
left a comment
There was a problem hiding this comment.
Reviewer: model_agent · GPT-6 Astra Pro · OpenAI · self_reported
动机 / Motivation
使用 benchmark 显式 CLI 激活流程的操作者,需要先在隔离副本中读取原生会话,确认源容器可以安全切换未来子进程使用的 CLI。 此前逐文件复制可能把 native home 留成 root 所有,非 root 读取器因无法写初始化文件而使观察失败;现在先查询读取器 UID/GID,准备私有目录,再复制已声明的状态成员。 本轮实际 POSIX 子进程验证了私有目录准备、0700 权限、SQLite 初始化及链接拒绝;原有真实结算读回与 typed 激活拒绝路径也通过。真实 Docker 的跨 UID 切换没有在本环境独立重跑。 不切换正在运行的用户容器,不增加执行额度、原生调用或自动更新入口,不把目录准备成功当作模型采用或完整 benchmark 资格。
本轮固定 head c685e09b7e0cbb786537ce75a5d3145af3417741,实际 base d3ac3bd8d69821ae5843b7cef5fdb6dcbc7cae74;对比 main c49d59b24d3f7745fccf3a1f2df1e35036fe517b,probe、激活/release 适配器、typed owner 及相关协议没有后续语义差异。
改动思路 / Approach
应在既有 disposable observer 的 I/O 边界修复目录所有权,读取身份来自该 observer 实际执行的 Python,而不是复制源路径的显示元数据;源状态和激活许可继续由现有 owner 决定。 本次只准备 observer 内物理 native home,并在准备失败时返回 unavailable 与清理 observer;原 pause、Stop、源 witness、受限复制和 launcher 资格规则保持原 owner。
已有流程先在当前控制和 worker lock 下暂停源容器,再创建网络禁用的观察容器,复制限定成员并进行只读资格检查。新增 helper 位于不可变读取依赖复制之后、状态文件复制之前,先以声明的读取用户查询真实数值身份,再在观察容器内准备目录。它没有把 reader 改为 root,没有复制整个 credential home,也没有替代 native history、原结算和源稳定性检查。
具体改动 / Changes
两个文件共 +62/-2:生产文件 +34/-1,显式 Docker 回归 +28/-1。依据为 base 的host-cli-source-activation-v0 协议。O1「隔离、私有、物理的 reader home」由 helper 实现;本轮验证了实际同 UID 的 POSIX 执行,真实 Docker 跨 UID 验证保留边界。O2「观察不可用时拒绝并清理」、O3「保留原结算、Stop 与显式激活范围」已分别由失败调用链和既有 owner 测试覆盖。
关键代码讲解
_prepare_observer_native_home严格解析实际 euid/egid,创建前后核对物理路径,使用数值身份 chown,并设为 0700。失败状态返回 false,不能从不完整输出推断可用。PausedSourceProbe.__init__改用已有_guest_path校验 native home;后续仍保留 credential home 排除和 native store 允许列表,没有新增可复制成员。PausedSourceProbe.__call__在准备失败时返回ObserverNativeHomeUnavailable和源 witness,执行现有finally清理观察容器,不进入后续状态复制或 launcher 资格通过路径。
对主干的风险 / Risks
主要风险是修改了符号链接目标、身份不可用却继续复制,或者把目录可写误当作源可切换。这些边界在代码中保持明确:输入路径须规范且物理,UID/GID 输出须完整,准备失败立即 unavailable;真正的源写入和恢复许可仍由既有 TypeScript owner 决定。没有新增持久状态、产品入口、额度重置或源写入操作,两个额外的 observer exec 与这条权限缺口相称。
本轮独立 PASS:9 个 helper/POSIX 用例(1.19 秒),运行候选生成的真实 Python 子进程,覆盖缺失目录、0500 不可写目录、0700 修复后的 SQLite 初始化、符号链接及符号父目录目标不变、非法/失败身份、非目录目标,以及实际 helper 失败后 probe 不再复制状态且清理 observer。这里 exec_run 的桥接在当前实际 UID/GID 1000 下执行,完整 probe 的 Docker 运输使用 stub;没有模拟或声称验证 root 到另一 UID 的 Docker 分派。
另外 PASS:2 个真实 File/SQLite CLI 结算读回用例(23.67 秒),验证未结算时不允许切换、原结算完成后才可通过、Stop 后拒绝,且观察不增加 debit;PASS:29 个 typed activation 用例,覆盖未知/不可用观察、其他身份、原生未完成状态、Stop、launcher 比较及恢复;Python syntax 和 diff check 通过。
环境没有 Docker daemon,未运行显式 Docker suite,也没有采用作者自评中的 Docker 数量作为本轮独立通过证据。真实 Codex、活动容器切换与同会话采用均未验证。远端 packet 的 checks 不可用,CI 仍是未知诊断;这份代码 review 不声明 merge/release qualification 已齐备。
我的整体评价 / Verdict
建议 APPROVE 这个有界权限修复,未发现阻止当前 head 的代码缺陷。长程流程减少了因观察容器初始化权限而误拒绝有效源的路径;操作者仍得到明确的 unavailable 与既有恢复边界。实际同 UID POSIX 结果、失败控制和原资格 owner 支持当前代码判断,但跨 UID Docker qualification 仍需使用现有显式 suite 验证,不能从本地桥接结果推导已运行通过。
本次使用现有路径与身份规则,仅增加本地 I/O 诊断,没有创建新的公共语义词汇。这是隔离 observer 的文件系统准备,没有渲染界面或 Agent 决策文本变化;实际权限、读回与失败结果比视觉图更直接。 未独立运行真实 Docker、root 到另一 UID 的 ownership 切换、真实 Codex 启动或活动 benchmark 切换。
English verdict: APPROVE
CLI activation can reject an otherwise idle source when the isolated reader's Codex home is created by the per-file copy as root. Codex exits during initialization because its unprivileged app-server cannot write local state. The existing refusal keeps the old launcher in place.
Provision the observer's native home for the reader's actual UID and GID before copying the declared store members. The directory stays private and credential files remain outside the copy. A failed setup still refuses activation; the source process, settlement and release checks are unchanged.
Validation: reproduced the failure on a network-disabled copy of the same native store and recovered the read by changing only the observer directory ownership. The shared fix also passed the same-copy readback, 24 Docker/CLI tests and 29 typed activation tests.