Volume 2 · Chapter 29
审批、权限与沙箱:模型动作的闸门
这是 harness 的「信任边界」域:审批(approval)拦「要不要做」,权限(permission)管「哪些动作免审批」,沙箱(sandbox)限「做的时候能碰什么」。三者叠在 14 页工具流水线的 pre-execute 与 15/16 页的执行世界上。
(卷一连接点) 14 页 pre-execute 的 ask · 17 页 approveEscalation · 16 页 subprocess
→
本域:user-approval / permission-presets / sandbox / sandbox-local / sandbox-policy / bash-sandbox / pwsh-sandbox
→
(回心脏) 审批结果决定 14 页流水线 allow/deny/ask
示例本次示例:模型要联网时的升级审批
示例轨迹 29-1 · sandbox_permissions 升级(挂载 bash-sandbox 时)
# 沙箱化 shell 下,模型想 curl 一个外网 URL:
# bash({command:'curl ...', sandbox_permissions:['network']})
# → tool-bash 能力探针:ctx.shell.sandboxMode 非 undefined(17 页 192 行)
# → approveEscalation(17 页 223-227 行)→ approver.request
# → approval/request waterfall(user-approval/src/index.ts:192 的服务)
# → 用户在 UI 看到「模型请求 network 权限」→ 批准/拒绝
# → 批准:本次调用带升级权限执行;拒绝:按原沙箱权限(无网络)执行或失败
# 这是「默认沙箱 + 升级要审批」两段式的完整实例
来源:17 页 223-227 行 + 29 页 §3
示例轨迹 29-2 · 权限预设决定免审还是必审
# 模型:bash('ls -la')(本地 shell,无沙箱升级)
# 14 页 pre-execute → permission-presets(inject=['shell','approval','sessions']):
# 读命令类型 → 「只读命令」→ 预设规则命中 → allow(免审)
# 模型:bash('rm -rf build/') → 「破坏性命令」→ 预设要求审批
# → PreToolDecision: ask → approval/request → 用户确认
# 预设的「会话记忆」:本会话已批准过的同类命令可跳过(sessions 依赖的用途)
来源:29 页 §3 + permission-presets/src/index.ts:175,196
§1挂载条目
approval → @deepseek-ai/dsh-user-approval——审批服务permission → @deepseek-ai/dsh-permission-presets——权限预设(175 行)sandbox → dsh-sandbox-local——本地沙箱sandbox-policy → dsh-sandbox-policy——沙箱策略bash-sandbox / pwsh-sandbox——沙箱化 shell provider(15 页 sandboxMode 的 override 实现)
§2包文件地图
| 包 | 规模 | 角色 |
|---|---|---|
packages/interaction/user-approval/ | — | ApprovalService extends Service(src/index.ts:192)——approval/request waterfall 的派发方 |
packages/interaction/permission-presets/ | — | PermissionPresetService extends Service(src/index.ts:175),static inject = ['shell', 'approval', 'sessions'](196 行)——预设规则判断「免审还是必审」 |
packages/sandbox/sandbox-policy/ | — | SandboxPolicyService extends Service(src/index.ts:91)——沙箱模式解析 |
packages/sandbox/sandbox-windows-acl/ | 12 文件 / 2530 行 | Windows ACL 沙箱实现(平台专用) |
§3机制:审批链 → 权限预设 → 沙箱升级
- 审批链(14 页的 ask):
tools/pre-execute返回 ask 时,走approval/requestwaterfall——用户批准/拒绝。17 页的approveEscalation(sandbox_permissions 升级)也走它。 - 权限预设(免审清单):permission-presets 决定哪些动作默认允许(如只读文件命令)、哪些必审(如写文件)。它的 inject 里同时有 shell 和 approval——预设既看动作类型,也调审批。
- 沙箱(执行限制):sandbox-policy 解析当前沙箱模式;bash-sandbox 是沙箱化的 shell provider(override 15 页的 sandboxMode)。Windows 上还有 ACL 沙箱(sandbox-windows-acl,2530 行——平台级能力)。
§4关键代码
175export class PermissionPresetService extends Service {
196 static inject = ['shell', 'approval', 'sessions']
91export class SandboxPolicyService extends Service {
175, 196
权限预设的三个依赖面说明它的位置:shell(看命令类型)、approval(发起审批)、sessions(按会话记忆免审状态)。它是「审批的预处理器」。
91
sandbox-policy 是纯策略解析——它不执行沙箱,只决定「哪个沙箱模式生效」。执行者是沙箱化 provider(bash-sandbox 等)。
§5易错点
14 页的坍缩语义与审批的关系:mode: 'code' 下模型调非 run_code 工具,审批 ask 和 guards 都看不到(14 页 createExecution 的注释)——防止策略批准一个必然失败的调用。审批链不是万能的闸门,坍缩检查在它之前。
沙箱升级的审批走 approval/request(17 页 223-227 行)——模型请求 sandbox_permissions 升级时,升级本身是一个审批请求。这形成了「默认沙箱 + 升级要审批」的两段式安全模型。