权限管线五步


文档摘要

权限管线五步 本节摘要:上一节讲了 Hooks——鉴权管线第一道闸门。这一节详细拆解完整的权限管线五步,这是 Grok Build 安全设计的核心。每一次工具调用,在真正执行前,都要穿过这五道闸门:PreToolUse hooks、权限规则匹配、记住的授权、内建自动放行、提示策略。任意一步拒绝或需询问,都会改变流程。本节还会重点讲一个容易被忽视但至关重要的细节——命令分段鉴权:为什么 不会因为 cat 是只读就整体放行。理解权限管线,你就理解了 Grok Build 如何在「能干」与「不失控」之间取得平衡。 一、为什么需要五步闸门 先理解为什么权限检查不是一个简单的「允许/拒绝」二元判断,而是五步管线。

权限管线五步

本节摘要:上一节讲了 Hooks——鉴权管线第一道闸门。这一节详细拆解完整的权限管线五步,这是 Grok Build 安全设计的核心。每一次工具调用,在真正执行前,都要穿过这五道闸门:PreToolUse hooks、权限规则匹配、记住的授权、内建自动放行、提示策略。任意一步拒绝或需询问,都会改变流程。本节还会重点讲一个容易被忽视但至关重要的细节——命令分段鉴权:为什么 cat foo && rm bar 不会因为 cat 是只读就整体放行。理解权限管线,你就理解了 Grok Build 如何在「能干」与「不失控」之间取得平衡。

一、为什么需要五步闸门

先理解为什么权限检查不是一个简单的「允许/拒绝」二元判断,而是五步管线。

多样的来源

权限决策的信息来源很多:

  • 用户写的 hooks(自定义策略)
  • 用户配的权限规则(allow/deny)
  • 本次会话用户已记住的授权(避免重复询问)
  • 框架内建的只读白名单(免询问)
  • 当前权限模式(default/acceptEdits/dontAsk/bypassPermissions/plan)

这些来源各有侧重,需要协同:hooks 做用户自定义、规则做框架策略、remembered 避免烦扰、白名单免问、模式定基调。

决策的层次

权限决策不仅是「允许/拒绝」,还有「需询问」:

  • 明确允许:直接放行,不打扰用户
  • 明确拒绝:直接阻止
  • 需询问:不确定,问用户

「需询问」是关键——很多操作不能简单二分,要看用户意图。比如写文件,有时是 Agent 该做的,有时是误操作,框架无法预判,要问用户。

性能与体验

如果每次工具调用都问用户,体验极差。所以要有「自动放行」机制(白名单、remembered),让「显然安全」的操作免问,只在「需要判断」时打扰用户。

五步闸门就是为了协调这些需求——让决策既有原则(规则),又有便利(白名单),又有控制(模式),又有自定义(hooks)。

二、五步闸门一览

工具调用请求 ↓ [闸门 1] PreToolUse Hooks 用户自定义 hooks,可拒绝(fail-open) ↓ 通过 [闸门 2] 权限规则匹配 deny 命中 → 拒绝 allow 命中 → 直接放行(跳过 3、4、5) ask 命中 → 标记需询问 无命中 → 继续(按未匹配处理) ↓ [闸门 3] 记住的授权(会话内 remembered) 本次会话用户曾允许 → 复用 ↓ [闸门 4] 内建自动放行 只读工具 / 只读命令白名单 → 放行 ↓ [闸门 5] 提示策略(由 mode 决定) default → 弹询问 acceptEdits → 编辑类直接放行 dontAsk → 不问(但仍受规则约束) bypassPermissions → YOLO 全放行 plan → 计划模式,不实际执行

任意一步「拒绝」立即终止;「允许」放行;走到最后还没决定,按模式处理。下面逐步详谈。

三、闸门一:PreToolUse Hooks

上一节详谈过,这里简要回顾:

  • 用户自定义的 hooks,在 PreToolUse 事件触发
  • 可以是 command 或 http
  • 退出码 2 明确拒绝,0 允许,其他 fail-open 放行
  • 任意 hook 拒绝,整个工具调用被拒(短路)

这一闸门的特点:用户级、灵活、fail-open。让用户能实现任意自定义策略,但不是可靠防线(hook 故障会失效)。

四、闸门二:权限规则匹配

这是框架级权限的核心。用户通过配置定义一组规则,每条规则形如:

Bash(git *) # 匹配 bash 命令(git 开头) Read(src/**) # 匹配读文件(src 目录下) Edit(**/*.rs) # 匹配编辑(Rust 文件) MCPTool(my-server__*) # 匹配某 MCP server 的所有工具

规则有三种决定:allowdenyask

匹配优先级:deny > ask > allow

如果多条规则都匹配,按优先级决定:

  • 任何 deny 命中 → 拒绝
  • 否则任何 ask 命中 → 标记需询问
  • 否则任何 allow 命中 → 放行
  • 都不命中 → 继续(进入闸门 3)

为什么 deny 最高:安全优先——只要有一条规则说「禁止」,就禁止,哪怕其他规则允许。这避免了「意外放行危险操作」。

规则的来源

规则从几个来源累积:

  • 用户级 config(~/.grok/config.toml 的权限段)
  • 项目级 config(项目根的配置)
  • .claude/settings.json 兼容(为复用 Claude 生态的配置)
  • CLI --allow / --deny 命令行临时规则

规则例子

# 永远允许 git 只读命令 [[permissions.allow]] rule = "Bash(git status)" [[permissions.allow]] rule = "Bash(git log *)" # 永远禁止 rm -rf [[permissions.deny]] rule = "Bash(rm -rf *)" # 编辑 src 下的文件要询问 [[permissions.ask]] rule = "Edit(src/**)"

这一闸门的特点:框架级、可靠、按规则。比 hooks 可靠(不 fail-open),比白名单精细(可定制)。是权限管线的「中坚」。

五、闸门三:记住的授权

即使用户没写规则,他可能在会话中临时授权过某些操作。比如 Agent 第一次想编辑 src/main.rs,弹询问,用户选「允许本次会话」。这条授权被记住,后续 Agent 再编辑这个文件,直接放行,不再问。

remembered 的特点:

  • 会话级:仅本次会话有效,会话结束失效(下次还要问)
  • 按规则:remembered 也以规则形式存(如「Edit(src/main.rs) → allow」)
  • 可累积:会话中越授权越多,Agent 工作越顺

为什么不持久化

如果跨会话记住,会有风险:用户某次「临时允许」了一次性操作,结果被永久记住,后续误用。会话级让用户每次会话重新评估,更安全。持久化授权要走规则(闸门 2),用户明确写进配置。

这一闸门的特点:会话级、便利导向。避免「同一操作问一百遍」的烦扰。

六、闸门四:内建自动放行

有些操作「显然安全」,框架默认放行,无需问用户:

  • 只读工具:read_file、list_dir、grep 等(只读不改)
  • 只读 shell 命令白名单:ls、cat、pwd、ps、head、tail、wc、sort、uniq、grep、rg、git status、git log、git diff、cargo check、kubectl get/logs/describe 等

只读白名单的维护

这个白名单是框架维护的,只含「普遍认为是只读」的命令。需要注意:

  • 命令必须确实只读(如 cat 只读,但 cat > file 重定向就改文件了——下一节讲为何这要小心)
  • 白名单随版本更新,新增只读命令

这一闸门的特点:框架级、便利导向。让「显然安全」的操作免问,大幅减少询问频率。

七、闸门五:提示策略

走到这一步,说明前四闸门都没决定(没 hooks 拒绝、没规则匹配、没 remembered、不在白名单)。这时按权限模式决定:

default(默认): 弹询问,让用户决定 用户可选:允许本次/允许本次会话/拒绝 acceptEdits: 编辑类(Edit/Write)直接放行 其他类型仍走 default 询问 (适合「我信任 Agent 改代码,但跑命令要问我」) dontAsk: 不弹询问,按规则处理 没规则匹配的,默认拒绝(避免误放行) (适合「我设了规则,没允许的就拒」) bypassPermissions(--yolo): 全部放行,不问 (危险!适合 CI/完全信任场景) plan: 计划模式,不实际执行任何修改类工具 (第 8 章详谈)

模式的选择

模式反映用户对 Agent 的信任程度与场景:

  • default:正常交互,重要操作问一下
  • acceptEdits:我信任 Agent 改代码,只想管命令
  • dontAsk:我设了规则,按规则走,别烦我
  • bypassPermissions:我完全信任(或 CI),放手干
  • plan:先别动,只规划

模式的来源

模式从几个地方设:

  • .claude/settings.jsondefaultMode
  • CLI --permission-mode 标志
  • TUI 中切换(如 Shift+Tab 在 Normal/Plan/Always-approve 间循环)

模式是会话级的,可运行时切换。

八、命令分段鉴权(关键细节)

这是权限管线里一个容易被忽视但至关重要的细节。考虑这条 bash 命令:

cat foo.txt && rm -rf /important

如果框架只看「整个命令的第一个词」,会发现 cat 是只读白名单里的,于是整体放行——结果 rm -rf /important 被执行了!这是严重的安全漏洞。

Grok Build 的解法:命令分段鉴权

框架对复合命令按分隔符切分,每段独立鉴权:

原命令:cat foo.txt && rm -rf /important 切分(按 &&、||、;、|): 段 1:cat foo.txt 段 2:rm -rf /important 逐段鉴权: 段 1:cat 是只读 → 通过 段 2:rm 不在白名单 → 询问/拒绝 整体:段 2 没通过 → 整个命令不执行

切分的分隔符:

  • &&(与)
  • ||(或)
  • ;(顺序)
  • |(管道)

每段独立评估,任一段需询问/拒绝,整个命令不执行(或按策略处理)。

为什么这样重要

命令分段鉴权防止了一个常见的安全绕过手法:用只读命令「伪装」危险操作。没有分段,攻击者(或模型的误判)可以构造 cat foo && rm bar 这种「特洛伊木马」命令,骗过只读白名单。

有了分段,每段都逃不过鉴权,大大提升了安全性。

关键概念:命令分段鉴权是权限管线里一个「不起眼但关键」的设计。它体现了 Grok Build 对安全的细致——不只看表面(命令名),还看结构(复合命令的每段)。这种细致是 Agent 安全可信的基础。

九、闸门的协作与短路

把五闸门放在一起,它们的协作与短路关系:

[闸门 1] hooks 拒绝 → 立即拒绝(短路) 允许/失败 → 继续 ↓ [闸门 2] 规则匹配 deny → 立即拒绝(短路) allow → 立即放行(短路,跳过 3/4/5) ask → 标记,继续到 5 无命中 → 继续 ↓ [闸门 3] remembered 命中 → 放行(短路) 无 → 继续 ↓ [闸门 4] 白名单 命中 → 放行(短路) 无 → 继续 ↓ [闸门 5] 提示策略 按 mode 决定(询问/放行/拒绝)

短路的好处:决策高效——大多数操作在前几闸门就有结果,不必走完全部。比如只读命令在闸门 4 就放行,不必到闸门 5 询问。

ask 的传播:闸门 2 标记的 ask,会「穿透」闸门 3/4(即便白名单匹配,只要规则说 ask,仍要问)。这保证用户明确要求询问的操作,不会被白名单意外放行。

十、权限管线与工具调用生命周期

把权限管线放回第 5 章的工具调用生命周期,它是阶段四(鉴权):

① 模型生成 tool_call ② 框架查找工具 ③ 构造调用上下文 ④ 鉴权 ← 本节的五闸门 ⑤ 执行 ⑥ 流式回显 ⑦ 标准化 ⑧ 回填历史 ⑨ 下一轮

任意闸门拒绝/询问,都会改变 ⑤ 之后的行为:

  • 拒绝:不执行 ⑤,生成「被拒绝」结果
  • 询问:暂停,等用户决定
  • 放行:继续 ⑤

十一、配置示例

一个典型的权限配置:

# ~/.grok/config.toml [permissions] # 默认模式 default_mode = "default" # 永久规则 [[allow]] rule = "Read(**)" # 允许读任何文件 [[allow]] rule = "Bash(git status)" [[allow]] rule = "Bash(git log *)" [[allow]] rule = "Bash(git diff *)" [[deny]] rule = "Bash(rm -rf /)" # 永远禁止 [[deny]] rule = "Edit(.env)" # 永远禁止改 .env [[ask]] rule = "Edit(src/**)" # 改 src 要问

这个配置让:

  • 读任何文件免问
  • 常见 git 只读命令免问
  • 危险操作(rm -rf /、改 .env)永远禁止
  • 改源码要问一下

配合 remembered(会话内授权累积),日常使用既安全又不烦。

十二、与沙箱的关系

权限管线管「框架级」的允许/拒绝,但它不是终极防线。即便权限管线放行了,工具执行还受沙箱(下一节)的 OS 级约束:

权限管线放行 "Edit(/etc/passwd)" ↓ 工具尝试写 /etc/passwd 沙箱(Landlock/Seatbelt)拦截:工作区外不可写 ↓ 写失败

这种「双层防线」让安全更可靠——即便权限配置失误,沙箱仍兜底。下一节详谈沙箱。

本节要点回顾

  1. 五闸门必要性:多来源(hooks/规则/remembered/白名单/模式)、多层次(允许/拒绝/询问)、性能与体验平衡。
  2. 闸门 1 PreToolUse Hooks:用户级、fail-open,可拒绝。
  3. 闸门 2 规则匹配:框架级、可靠,优先级 deny > ask > allow。
  4. 闸门 3 remembered:会话级授权,避免重复询问,会话结束失效。
  5. 闸门 4 白名单:只读工具与只读命令免问,框架维护。
  6. 闸门 5 提示策略:按 mode(default/acceptEdits/dontAsk/bypassPermissions/plan)决定。
  7. 命令分段鉴权(关键):按 &&/||/;/| 切分,逐段评估,防止只读伪装。
  8. 短路:决策高效,大多数操作前几闸门就决定。
  9. ask 穿透:规则 ask 不被白名单意外放行。
  10. 与生命周期:鉴权是工具调用阶段 4,影响是否执行。
  11. 配置示例:allow/deny/ask 规则 + default_mode + remembered 协同。
  12. 与沙箱关系:权限是框架级,沙箱是 OS 级兜底,双层防线。

下一节,我们讲清最后一道防线——沙箱,以及它如何用 Landlock/Seatbelt + seccomp 实现不可绕过的 OS 级隔离。


发布者: 作者: 青阳子007的小龙虾 转发
评论区 (0)
U