执行权限与沙箱
本文定义请求身份、工具审批、运行中权限更新和本地进程隔离。Authority 表示认证主体及能力上限;Permission 判定一次操作;Sandbox 限制获准进程可访问的资源。适用范围包括 Web、CLI、ACP、渠道、嵌套 Agent、定时任务和恢复执行。
统一操作判定
审批等待与工具执行共用同一判定函数。顺序为:固定约束、Authority、计划模式只读限制、显式 deny、显式 ask 或强制审批、精确 Web Use 授权、bypass、显式 allow、定时 Memory 例外、安全读取、acceptEdits、Auto 分类、普通审批。非交互请求不能要求本地审批。bypass 只跳过普通审批与 Auto 分类,显式规则、强制审批、插件 gate 和 Sandbox 仍生效。非法模式更新必须拒绝。
Web 答复只有在规范等待命令确认 applied 后才移除问题。发送结果未知时锁定答复,使用相同命令标识重试;仅写入连接不代表完成。审批、普通提问、表单和讨论均遵循该约束。
委派权限判定与审计隐私
派生 Agent 与 MCP 的 write/edit 调用必须包含非空字符串目标;patch 中显式的空目标在 bypass 和 allow 规则之前拒绝。相对路径以绑定的工作目录解析;realpath 范围检查同时覆盖文件和父目录符号链接。独立调用文件安全辅助函数时,相对路径仍保留原有的进程工作目录语义。
委派的高风险工具经 bypass 或 allow 规则获准时发出 security.risky_tool_delegated;写入路径被拒绝时发出 security.path_violation。事件表示权限判定,不表示工具已完成执行;构造审批清单或恢复检查时可能重复产生。载荷仅包含会话、工具、来源、权限级别及适用的固定原因,不保存命令、代码、目标路径或其他参数原文。origin 使用 system,session metadata 沿用既有事件日志的位置与轮换规则。事件尽力投递,投递失败不改变权限结果。
权限模式
ask 放行安全读取,其他操作要求审批。acceptEdits 额外放行工作目录内支持的安全编辑。plan 按既有只读工具策略拒绝副作用。auto 放行安全工具,其余执行风险分类。bypass 跳过普通审批与风险分类。有效模式按会话、项目、ask 的优先级解析;实际 admission 和界面确认必须使用相同的有效值。
带版本的运行中权限
现有 SessionStore 持久化 permission_state,包含模式、版本和 owner principal。原子 compare-and-set 拒绝过时客户端的修改。设置入口验证认证身份、会话范围和预期版本。工具在下一次审批检查读取该身份所属的最新设置,单个调用保留检查结果直到执行;已获准的调用不被中途取消。原始身份、admission 和恢复合同保持不可变。其他会话、paired 渠道及非交互任务不能使用这些动态放宽。
切换模式后,只重新判断普通权限审批。现在允许的调用通过既有 canonical wait-answer 命令恢复。显式 ask、强制审批、Sandbox 升级和用户问题不自动回答。若更新与等待创建交错,旧执行释放 cancellation token 后再次检查;启动恢复也检查尚未处理的持久化变更。已结束、取消或超时的任务不会重新执行。
界面区分请求中、确认模式和错误;较旧的版本不能覆盖新状态。未发送的草稿只保存本地选择,首次发送时传入。已有会话必须等待后端确认。计划模式在工具边界实施,因此能阻止模型已经提出但尚未获准的写入;工具目录保持稳定以支持中途退出计划模式和恢复执行。模型主动进入的计划状态仍需要批准 exit_plan_mode。每次后续模型请求也包含最新确认模式的运行时说明。
Web 和默认 App 在已有后端确认版本时立即发送权限修改,只有未知版本时才先读取。后端确认是生效边界,与模型是否正在推理或生成无关。确认后的每次普通工具审批检查使用新模式,包括同一批生成结果中的后续调用;无需重启模型请求或等待下一条用户消息。版本冲突仍返回错误,界面不把尚未确认的选择显示为有效模式。
工具与宿主边界
文件工具执行进程内检查;macOS 子进程使用 Seatbelt,Linux 使用 bubblewrap。Browser/Web Use 使用精确 surface 授权。Docker 与 SSH 使用各自的执行边界;owner 配置的 MCP 进程不等于本地 Sandbox。workspace-write 限制写根、保护读取、过滤凭证环境并默认关闭网络;danger-full-access 使用宿主用户权限。后端缺失默认 refuse;warn 是显式回退。自动导入的 agentic applications 路径保持固定写入限制。
Sandbox 是会话 override,并在 turn 开始时冻结。修改开关只影响后续 turn,不影响当前进程、其他会话、定时任务或子任务继承的策略。普通审批不能关闭 Sandbox;bypass 不自动升级 Sandbox。
Sandbox 升级与精确审批
只有带 approval.request 的交互本地 owner 可以批准精确升级;保护应用路径和凭证过滤仍保留。always_path 只能记录具体可放开的读取路径。审批绑定会话、execution、工具和 tool call,普通工具审批不能复用为 Sandbox 升级。当前执行协议没有工具返回后的独立升级等待,实际拒绝需要用户显式修改设置后发起新调用,不能静默复用普通审批。paired、MCP、cron 和 subagent 不具备升级能力。
参考框架与取舍
保留既有参考语料:Claude Code 的权限模式、独立 Sandbox 与 Auto 概念;Codex CLI 的结构化违规和精确重试;OpenClaw 的凭证过滤、后端拒绝及嵌套分类;Hermes Agent 的固定规则、命令规范化及非交互拒绝;OpenCode 的工具和资源级规则;pi-mono 的扩展拦截与非交互拒绝。Aider 的 Git 恢复不替代安全边界;Goose / WeClaw 类适配不能自动代替 owner 审批。未重新核实上游最新版本,不将这些比较表述为本次实测结果。
不采用项目配置静默覆盖全局安全规则、自动选择 Docker、外部渠道自动批准,以及将可选隔离显示为默认隔离。每工具 Sandbox override 和完整后台 Auto 产品流程仍未实现。
已核查的权限对比
Claude Code 权限文档明确 deny、ask、allow 优先级、下一次工具调用采用规则变更,以及单次允许或拒绝时附加评论。OpenProgram 保留显式规则优先级和当前会话讨论,但未实现先执行再向模型提供批准评论的行为。
OpenCode V2 权限文档采用最后匹配规则、项目范围持久授权和同会话拒绝传播。OpenProgram 有意保留 deny 优先、精确操作授权和单个规范等待目标。OpenCode V2 子 Agent 使用自身策略;OpenProgram 通过父身份及权限快照约束子任务准入。这些属于明确的设计差异。
当前审查修复要求答复确认、刷新后正确执行版本及服务端定义授权范围。一次性自更新审批和不能表示精确规则的操作只提供单次允许,规范命令执行同一范围校验。这些修复的运行验收尚未完成。
OpenAI 的 Codex 运行说明区分沙箱执行边界与审批策略,支持单次和会话范围授权,并介绍托管约束与审批遥测。OpenProgram 保留这一区分,但记住操作的规则作用于项目,不是会话。域名策略、企业托管约束和远程审计导出不是 OpenProgram 已具备的同等能力,仍是明确限制。
失败与兼容性
缺失身份、过时版本、非法模式、能力拒绝、显式规则、分类失败和 Sandbox 拒绝需要可区分。任何失败都不回退为 owner 或 bypass。没有 permission_state 的旧会话继续读取 permission_mode;新认证提交携带完整身份。旧 admission 缺失身份时必须经认证入口重新提交,恢复流程不为其提权。
宿主进程限制可能阻止 ps、top 和 lsof;Docker socket 不自动暴露。Linux 通配路径遮蔽存在平台限制。域名和端口 allowlist 需要受管代理与重定向校验,目前未实现;浏览器和远程网络控制独立。
代码职责与验收
agent/authority.py 定义身份和能力;agent/permissions/state.py 管理版本化状态和原子更新;policy.py 管理统一操作判定、显式规则和硬限制;classifier.py 管理 Auto 风险判定,仅接受 JSON 布尔 true 放行;approval.py 管理审批清单、精确等待消费和工具执行;lifecycle.py 管理调用快照与持久化等待恢复;session_config.py 解析配置;production_driver.py 保留 admission、恢复和等待生命周期;WebSocket 设置入口处理认证与确认;Web 和 CLI 显示确认状态、更新中和错误。
验收覆盖真实聊天身份与继承模式、安全工具、运行中双向切换、待审批恢复、显式 ask/deny、强制审批、计划模式、跨会话和身份隔离、版本冲突、刷新重连,以及 Sandbox 不变。
跨平台审批文件写入
审批后的 edit、write 和 apply_patch 共用 file_state.write_checked。调度入口和该模块在 Windows 上不导入 Unix 专属模块。文件锁复用现有兼容层,文件以二进制模式打开,POSIX 保留 O_NOFOLLOW。
写入方检查审批记录的内容与身份,以不截断方式打开文件,加排他锁后通过已打开描述符计算摘要,并在修改前检查路径身份和解析目标。路径复核只读取元数据,不通过第二个句柄读取内容,避免 Windows 字节锁拒绝同进程其他句柄的读取。符号链接和 reparse 条目被拒绝;审批时不存在的文件使用排他创建。路径回退检查写入前的替换,不声称具备描述符相对操作对任意并发父目录替换的保护。
验收覆盖无 fcntl 时调度入口导入、文件变更与删除、已有与新建文件、UTF-8 原始字节、替换与链接竞争,以及连续写入。Windows 安装检查导入真实调度入口,平台 CI 在完整单元测试前运行审批回归。
参考:Python fcntl 仅支持 Unix;现有 Windows 适配器使用 msvcrt 字节锁。复用适配器避免第二套锁实现,不能删除链接检查或跳过加锁。
实现状态
跨平台审批文件写入已通过独立规格审查、质量审查和本地定向回归。Windows x64 与 arm64 原生执行仍待验证;平台 CI 已加入共享写入和真实调度入口回归。这些局部证据不表示完整 Windows release 或安装后 App 验收完成。
当前审查覆盖策略优先级、绑定身份的实时权限设置、授权范围校验、全部 Web 答复入口、连接恢复、键盘操作,以及 Claude Code、Codex 和 OpenCode 官方资料对比。TypeScript、Python 语法和文档链接检查通过;不声称运行了完整仓库测试或新的独立 Agent 审查。
| 边界 | 证据 | 验证限制 |
|---|---|---|
| 审批恢复 | 已安装 App 刷新后恢复审批,单次允许后 printf 操作完成。 | 不代表验证了所有平台沙箱后端。 |
| 范围与拒绝 | 刷新前后选项一致;拒绝使执行结束,没有启动托管进程。 | 保存规则失败分支经源码检查,未注入文件系统故障。 |
| 问题答复 | 全部输入区展示共用确认提交逻辑,提问工具在执行前声明规范等待。 | 新等待声明的端到端验收尚未完成:一次模型请求仍未返回,另一次调用了无关工具,已拒绝。 |
| 策略与生命周期 | 共享策略及规范恢复保留显式规则、强制等待、身份边界和版本检查。 | 本轮为源码审查,不声称重新运行全部历史生命周期回归。 |
保留现有宿主隔离。域名允许列表、资源配额、Windows 沙箱、逐工具沙箱覆盖和完整后台自动分类界面仍是明确的产品限制。提问验收和最终安装完成前,不把整体审查标记为完成。