Skip to content
预计 1 分钟右侧目录可快速定位

高风险 Tool 怎样只拿最小权限:Risk、Least Privilege 与 Approval ​

前置:不可信输入怎样限制权限:Tool Result、Permission 与 Capability Security
核心问题:一个高风险 Tool 到底应该拿多少权限、何时需要 Approval,怎样保证“模型看见 Tool”不等于“模型可执行 Tool”?

读取公开网页是低风险;发送邮件为外部写;删除云资源是高风险不可逆,应强审批。Agent 只需读某 repo 时,挂只读子目录而不是整个 home + 云凭证。

Tool Risk Classification ​

按副作用、可逆性、数据敏感度和外部影响给 Tool 分风险等级,用于 approval、audit、sandbox 和限制策略。分类应落到执行 policy。

🔍 源码对照:Risk Hint 和 Enforcement 必须分开 ​

完整源码与通用分析见 06-03 Tool Metadata / Dynamic Discovery。这里不重复代码;这里关注 risk hint:annotations 只能为 policy / approval 提供输入,不能直接成为执行权限。

源码说明

Auto-review gate 把 host shell、box shell、MCP、computer、automation write、cloud agent、subagent 分成不同 surface,并在 pending approval 时阻止新 side effect。这是 least privilege 的一个工程化表现:权限不是“Agent 有/没有超级权限”的单 bit,而是按 capability surface 和当前状态收缩。

工程边界

Auto-review classifier 的结果不能替代真正 sandbox/authorization;分类错误时仍需要 hard capability boundary 限制 blast radius。

Shadow Harness 对照

  • ToolSpec/RiskPolicy 显式定义 read/write/network/credential scopes。
  • Approval 只临时扩大某个 action 的 capability,不永久提升 Agent 全局权限。

验证

批准一次 write_file:/workspace/a 后尝试写 /etc/hosts;即使同属 shell/write 类别也必须被 least-privilege scope 拒绝。

Least Privilege ​

只授予当前任务所需最小读写/网络/资源范围;不可逆、外部通信、生产变更、金钱等动作通常需要更高审批。Least Privilege 要把主体、能力、资源和时间范围都缩到完成当前任务所需最小集合。对 Agent 来说,不只是“少给几个 Tool”,还包括目录只读/可写范围、网络目标、OAuth scope、secret 生命周期和单次 Run 的临时授权;默认全开再靠 approval 弥补,会产生 approval fatigue 和更大的 blast radius。

每个 Run/Agent 只获得完成当前任务所需最小资源、路径、网络目的地和 token scope,并及时撤销。权限越宽,prompt injection 的可利用面越大。

Approval Boundary ​

Approval 必须发生在高风险副作用真正提交之前,而且用户看到的内容要足够具体。

text
Model proposes delete_project(project=abc)
→ validate + risk classify
→ approval shows exact project/action
→ approve
→ execute

如果先执行再弹确认,approval 已经失去意义;如果只批准“允许 Agent 做危险操作”,scope 又太宽。审批结果还要绑定 action/version,避免批准后参数被悄悄替换。

🔍 源码对照:真正的 side-effect gate 在 Runtime Controller ​

完整源码与通用分析见 11-05 HITL / Approval / Resume。这里不重复代码;这里关注 enforcement:approval 的真正 gate 位于 Runtime Controller,模型输出或 metadata 风险提示都不能替代执行时授权。

同一个 Tool 名称也可能有不同风险 ​

“shell”不是一个固定风险等级。下面三个调用的 blast radius 完全不同:

text
pytest tests/auth              → workspace read/execute,通常低到中风险
pip install unknown-package    → network + supply-chain + code execution
rm -rf /some/path              → destructive filesystem write

因此风险判断最好结合 capability + arguments + target + credential + environment,而不是只按 Tool 名称打标签。

Least Privilege 的目标是默认只给当前任务必需能力;Approval 则用于跨越预先定义的高风险边界。审批通过也应绑定具体 operation,例如“允许这次向 production 部署 version X”,而不是给 Agent 一个永久 admin=true。

Failure Modes ​

所有高风险动作都弹 Approval 导致 Approval Fatigue ​

症状: 用户频繁看到无法判断差异的“允许?”提示。

为什么危险: HITL 失去监督价值。

处理: 风险分级 + 最小 capability + 参数级上下文,只在重要边界请求审批。

如何验证 ​

Case断言
所有高风险动作都弹 Approval 导致 Approval Fatigue统计 approval 数与真实高风险动作覆盖率,低价值提示应被消除。

关联源码 ​

Codex 源码对照:Authorization / Approval ≠ Sandbox Containment ​

要回答的问题 ​

一次 command 的 policy decision 与实际 sandbox containment 怎样共同参与 execution?为什么不能写成 exec_policy.rs = authorization、sandboxing.rs = sandbox 这种“一文件一概念”映射?

精确定位 ​

Tag: rust-v0.150.1

File:

Symbols:

  • ExecPolicyManager::create_exec_approval_requirement_for_command(...)
  • prompt_is_rejected_by_policy(...)
  • ExecApprovalRequirement::{Skip, NeedsApproval, Forbidden}
  • default_exec_approval_requirement(...)
  • sandbox_override_for_first_attempt(...)
  • SandboxAttempt
  • SandboxAttempt::env_for(...)
  • SandboxAttempt::env_for_exec_server(...)
  • SandboxManager::select_initial(...)
  • SandboxManager::should_sandbox(...)
  • SandboxManager::transform(...)
  • SandboxTransformRequest
  • SandboxExecRequest

最小调用链 ​

Policy / authorization side:

text
command
+ AskForApproval
+ PermissionProfile
+ exec policy rules
→ ExecPolicyManager::create_exec_approval_requirement_for_command(...)
→ policy evaluation
→ ExecApprovalRequirement
   ├─ Forbidden
   ├─ NeedsApproval
   └─ Skip { bypass_sandbox, ... }

Containment side:

text
ExecApprovalRequirement
+ SandboxPermissions
+ FileSystemSandboxPolicy
→ sandbox_override_for_first_attempt(...)
→ SandboxAttempt
→ SandboxAttempt::env_for(...) / env_for_exec_server(...)
→ SandboxManager::transform(SandboxTransformRequest { command, permissions, sandbox, network, ... })
→ SandboxExecRequest / ExecRequest
→ controlled execution

Unified exec 再把上述 policy/permission 结果与 cwd/environment/process request 合并后交给 process manager。

Source Fact ​

exec_policy.rs 把 Decision::Forbidden / Prompt / Allow 映射为 ExecApprovalRequirement::Forbidden / NeedsApproval / Skip。其中 Skip 还携带 bypass_sandbox,说明 policy result 本身就可能影响后续 sandbox orchestration。

core/src/tools/sandboxing.rs 不只包含 sandbox 类型:文件顶部明确说明它同时集中 approval flow primitives 与 sandbox orchestration traits。sandbox_override_for_first_attempt() 会同时查看 permission、approval requirement 和 filesystem sandbox policy;SandboxAttempt::env_for() / env_for_exec_server() 再调用 codex_sandboxing::SandboxManager::transform(...)。SandboxManager 的真实定义在 codex-rs/sandboxing/src/manager.rs:select_initial() / should_sandbox() 负责判断初始 sandbox 类型,transform() 则把 SandboxTransformRequest 转换为 host-native SandboxExecRequest。

因此:

text
概念层:Authorization / Approval ≠ Sandbox Containment
实现层:exec_policy.rs + tools/sandboxing.rs + tool runtime 共同形成一次 decision

概念边界不等于源码目录边界。

Design Inference ​

最小权限 Harness 至少需要两个独立判断:

  1. Authorization / Approval:这次 action 是否允许、是否需要人工授权;
  2. Containment:即使允许执行,具体能读写哪些文件、访问哪些网络、使用什么 process capability。

Approval 不能替代 containment;sandbox 也不能回答“这次动作是否应该被授权”。

Codex-specific Trade-off ​

Codex rust-v0.150.1 的 execpolicy rule system、AskForApproval 枚举、permission profile、sandbox backend selection、bypass_sandbox 语义都是产品实现。别的 Harness 可以用 capability token、OPA/policy engine、container profile 等不同机制实现同一 invariant。

Shadow Harness Delta ​

  1. 权限模型拆成 AuthorizationDecision 与 ExecutionContainment,禁止单一 approved: bool 同时表达两层。
  2. AuthorizationDecision 至少有 ALLOW / NEEDS_APPROVAL / FORBID;containment 独立携带 filesystem/network/process capability。
  3. execution trace 同时记录 policy_decision 与 sandbox_profile,这样才能解释“被允许但仍被限制”的运行结果。
  4. 回归测试:用户批准一个 command 后,sandbox deny-read / network deny 仍必须有效;禁止因为 approval 自动升级成全局 unrestricted execution。

不要过度推导 ​

源码可以证明这两个概念在 Codex execution decision 中交叉协作,但不能推出 exec_policy.rs 完全等同于“Authorization 层”或 tools/sandboxing.rs 完全等同于“Sandbox 层”。文件组织是实现细节,Domain boundary 应由 authority 与 semantics 定义。

完整映射见 OpenAI Codex Source Map。

自测 ​

  1. 只为了读一个日志文件却给 Tool 整个主机 root 权限,违反了哪条最小权限原则?
  2. Approval 应绑定具体高风险动作、参数和时效。若只保存一个布尔 approved=true,恢复后可能出现什么越权?

Sources ​

AI Engineering · Agent · Harness · Backend Systems