2857 字
约 9 分钟
1
审批策略:同一条命令,问不问看哪两颗旋钮
无标签

OpenAI Codex · 代码模式 审批策略:同一条命令,问不问看哪两颗旋钮 默认问不问跟沙箱种类绑在一起。问过一次之后,记住的是完整命令,还是一段前缀。 一句话速览 默认问不问跟沙箱种类绑在一起。问过一次之后,记住的是完整命令,还是一段前缀。

课程目标 读完能说清两件事。同一条命令为什么会从直接放行变成必须有人点头。以及你点过一次 Yes 之后,下次还问不问,系统到底记住了什么。

先玩一遍 · 同一条命令,换策略看结局

四种策略,三种沙箱,看哪一格盖放行、问人、拒绝

播放 单步 重置

命令

git status npm run test npm run lint prompt 规则

前三条走 Allow。第四条命中 execpolicy 的 Prompt。

策略

OnRequest UnlessTrusted Granular Never

沙箱

read-only workspace-write danger-full-access

旋钮

关掉 sandbox_approval requirements 禁止全盘 按会话记住 按前缀记住

点格子也能跳到那一格。两套记住互斥。

十二格沙盘 · 只读和工作区常常盖同一张章 Restricted 两行会撞车

Codex OnRequest · workspace-write

等待 点播放,看同一条命令换策略之后盖哪张章。 给模型的说明书 策略还没选定。

DSH ask · workspace-write

等待 两颗旋钮独立。全盘可写仍可继续提问。 记住什么 只有 allowed-once。问过一次,下一次还问。

逻辑轨迹 · 动画每一步对应源码里的哪一段

读当前 turn 的 AskForApproval protocol.rs L924 看 FileSystemSandboxKind 是不是 Restricted permissions.rs L227 Never 给 Skip,UnlessTrusted 给 NeedsApproval sandboxing.rs L198 OnRequest 或 Granular 只在 Restricted 时要问 sandboxing.rs L200 Granular 要问且关掉沙箱审批则 Forbidden sandboxing.rs L209 execpolicy 的 Prompt 再过第二道闸 exec_policy.rs L214 会话缓存只收 ApprovedForSession,认精确 key sandboxing.rs L108 策略改了,给模型的说明书一起改 permissions_instructions.rs L271

点播放,看同一条命令从直接放行一路变到必须有人点头。

十二格里有几格一样 read-only 和 workspace-write 都是 Restricted。OnRequest 在这两行盖同一张问人章。danger-full-access 把 kind 拧成 Unrestricted,默认函数不再问。 Never 也会拒绝 策略要求提问时,Never 把提问升级成拒绝。关掉 sandbox_approval,只挡住本来要弹的窗。文件系统已经 Unrestricted,Forbidden 分支进不去。 两套记住 按会话记住 npm run test,再跑 npm run lint,key 对不上还要问。按前缀记住才会把范围扩出去。常规弹窗默认露出的,是前缀那一条。

教学示意:舞台只演示判定函数和两套缓存的结构差异,不执行真实命令。逻辑轨迹右侧行号对应 openai/codex 仓库 commit 4f39251a01。

思路一 · 默认问不问,跟沙箱种类绑在一起

它解决什么问题 你把审批留在 on-request ,沙箱从 workspace-write 拧到 danger-full-access 。十分钟前那条出沙箱命令还会弹窗。现在不弹了。你没改审批旋钮。 审批策略 AskForApproval 是当前 turn 用哪套问人规则,类型里有四个变体。文件系统沙箱种类是三个,默认 Restricted ,意思是只读或只能写工作区。这两颗旋钮在同一个判定函数里。改其中一颗,另一颗的行为会跟着走。 出处: codex-rs/protocol/src/protocol.rs 第 924 至 947 行,以及 codex-rs/protocol/src/permissions.rs 第 227 至 232 行

思路是什么 一条命令先读审批策略,再看文件系统是不是 Restricted ,再让 execpolicy 把 Allow、Prompt、Forbidden 叠上去。execpolicy 是按命令文本给出三态的规则文件。 默认问不问写在 default_exec_approval_requirement 。Never 这一层给 Skip。UnlessTrusted 这一层给 NeedsApproval。OnRequest 和 Granular 只在 Restricted 时要问。 read-only 和 workspace-write 都是 Restricted,所以这两格的默认结局一样。 danger-full-access 把 kind 变成 Unrestricted,默认函数走 Skip。 出处: codex-rs/core/src/tools/sandboxing.rs 第 198 至 230 行 Granular 还多一个闸。需要审批、且 sandbox_approval 关掉时,直接 Forbidden。文件系统如果已经是 Unrestricted, needs_approval 先变成假,Forbidden 分支进不去。关掉沙箱审批,只挡住本来就要弹的窗。 Never 遇到 execpolicy 的 Prompt,提问会升级成拒绝。它并不表示什么都准跑。 出处: codex-rs/core/src/exec_policy.rs 第 214 至 236 行

命令到达 AskForApproval

文件系统 kind 是不是 Restricted

默认要求 Skip / 问人 / 拒绝

Allow 则开跑

Prompt 再过一闸 OnRequest 加 Unrestricted,默认 Skip。Never 加 Prompt,提问升级成拒绝。

教学化结构图:先出默认要求,再让 execpolicy 叠一层。

untrusted 写不进配置。类型还在,公开字符串已经退休。用户显式写出,整次加载失败。没写才看项目信任:已信任走 OnRequest,明确未信任走 UnlessTrusted。 出处: codex-rs/core/src/config/mod.rs 第 3607 至 3625 行 还有一个加载期硬拒绝。requirements 不允许 danger-full-access ,配置却写了 approval_policy = "never" ,加载器会先把权限档案回落到只读。只读加上从不提问,等于模型在窄沙箱里还没人可问。这种组合直接判非法。 出处: codex-rs/core/src/config/mod.rs 第 3969 至 3979 行

为什么长期成立 全盘可写时,再问一次出沙箱没有意义。两颗旋钮绑在一起,少弹窗。代价是改沙箱会静默带���审批行为。换个语言重写,仍要先回答:全权模式还要不要问人。 策略枚举靠穷尽分支表达规则。新加一个变体,编译器会逼所有判定函数表态。这是类型在替运行时守门。

思路二 · 问过之后,记住什么

它解决什么问题 弹窗上两条记住长得很像。一条是本会话记住这条命令。一条是把前缀写进 execpolicy,跨会话生效。点错了,后面的边界题就会答反。 常规 exec 弹窗默认菜单里,甚至没有 ApprovedForSession 。有网络上下文时才带上它。普通命令给一次批准,有前缀修正提案时再加按前缀记住,最后是取消。用户最常碰到的记住,是前缀那一条。 出处: codex-rs/protocol/src/approvals.rs 第 314 至 347 行

思路是什么 会话缓存活在 ApprovalStore 里,跟会话同寿命。key 是规范化后的完整命令,外加 cwd、环境和 execpolicy 指纹。所有 key 都已经是 ApprovedForSession 才命中。 Approved 一次放行不会进 map。 出处: codex-rs/core/src/tools/sandboxing.rs 第 64 至 116 行 npm run test 批准进会话, npm run lint 是另一把 key。 /bin/bash -lc 和 bash -lc 在能拆出单一明文命令时,缓存成同一组 token。会话缓存认完整命令,不认 npm * 。前缀扩张只走 execpolicy。 改审批策略不会清空这座 map。key 里没有 AskForApproval 。中途从 OnRequest 改成 UnlessTrusted,已经缓存的批准仍算数。改 execpolicy 会改指纹,缓存才会失效。

用户点决定 ReviewDecision

ApprovedForSession 精确 key 入会话抽屉

ApprovedExecpolicyAmendment 前缀写入规则文件

下次完整命令相同 才跳过弹窗

前缀匹配就放行 跨会话,范围更大 Approved 只放行这一次,不进 map。npm run test 和 npm run lint 是两把 key。 常规 exec 默认菜单常常只露出前缀这一条。

教学化对照:一层认完整命令,一层认前缀并落盘。

为什么长期成立 两套记住对应两种威胁。精确 key 挡不住换参数。前缀挡得住换参数,也容易把包装命令的范围扩太大。两层分开,才能各自配禁建议名单。一天弹窗不多的时候,先只做一次放行也成立。

思路三 · 策略改了,说明书一起改

它解决什么问题 策略改了,只改运行时分支不够。模型看到的说明必须同步改,否则它会按旧规则去要 require_escalated 。Never 下面如果说明书还在教它提权,运行时会把提问升级成拒绝,模型只会反复撞墙。

思路是什么 权限说明是一段 developer 消息。先选沙箱模板,再选审批模板。Never、UnlessTrusted、OnRequest 各有现成 markdown。Never 那份只有一句:不要再给 sandbox_permissions ,命令会被拒。Granular 没有第五份文件,按五个开关现场拼允许列表和拒绝列表。两套说明拼在同一段里,模型一次看到当前组合。 出处: codex-rs/prompts/src/permissions_instructions.rs 第 271 至 291 行 钩子在人前面。钩子给出 Allow 或 Deny,弹窗就不会出现。钩子的 Allow 是一次 Approved ,不写会话缓存。

策略改了,说明书必须一起改。

为什么长期成立 运行时和模型说明书是同一份合同的两面。判定函数改了,字典那一行必须一起改。把这两份放在同一个模块,用同一组测试喂两边,换语言也用得上。

横向对比 · 旋钮独立还是绑在一起

DSH:两颗旋钮,一次授权不扩大 DSH 的审批策略只有 ask 和 never 。 never 在分派给回答者之前就返回 rejected ,后挂的监听器改不了这个承诺。授权结果只有 allowed-once 。没有本会话缓存,没有前缀修正。问过一次,下一次还问。 出处: packages/interaction/user-approval/src/index.ts 第 84 至 94 行,以及第 304 至 312 行 沙箱和审批是两颗独立旋钮。用户看见的下拉框是预设表: workspace-write 绑 ask , danger-full-access 绑 never 。点下一档时分别调用两颗 setter。对不上表就显示 custom 。所以 DSH 可以单独把审批留在 ask 、把沙箱拧到全盘可写。Codex 的 OnRequest 在 Unrestricted 上默认 Skip,这个组合在默认函数里不可独立存在。 出处: packages/interaction/permission-presets/src/index.ts 第 167 至 176 行 两侧均已核对源码 · 2026-08-22 · DSH · 审批与权限

Claude Code:记住写进规则表 Claude Code 对外的权限模式是五档,外加内部的 auto 和 bubble 。规则来源包括 userSettings 、 projectSettings 、 session 、 cliArg 。判定先查整工具级 deny,再往下走。 出处: restored-src/src/types/permissions.ts 第 16 至 29 行,以及 restored-src/src/utils/permissions/permissions.ts 第 1169 至 1181 行 alwaysAllowRules 可以按来源记下允许项, session 是其中一档。下次按规则匹配,不必完整 argv 相等。代价是匹配函数必须自己防包装。Codex 把扩大范围交给 execpolicy 前缀和禁建议名单。 dontAsk 接近 Never。Codex 没有公开的全放行审批策略,Never 仍会被 execpolicy 拦住。 出处: restored-src/src/types/permissions.ts 第 54 至 62 行,以及第 433 行 两侧均已核对源码 · 2026-08-22

课堂练习

01

拧沙箱,弹窗还在吗 审批留在 on-request ,沙箱从 workspace-write 拧到 danger-full-access 。再跑一条会写工作区外路径的命令。弹窗还在不在?为什么? 接着把同一条 npm run test 按会话批准,再提交 npm run lint 。缓存该不该命中?如果点的是按前缀记住,答案会不会变?

Takeaway: 同一条命令问不问,看审批策略和文件系统是不是 Restricted。Never 遇到必须提问的规则,提问会升级成拒绝。问过之后的记忆分两层:会话层认精确 key,持久层才允许前缀。策略改了,给模型的那句话必须一起改。

审批策略:同一条命令,问不问看哪两颗旋钮
http://www.clxhxhhr.top/posts/4061/
作者
clxstart
发布于
2026-09-25
许可协议
CC BY-NC-SA 4.0
评论
0 条
还没有评论,先写一条吧。