goose/source-notesupstream ↗
goose · version 1.45.0 · Rust 1.94.1

第 6 章:权限与安全——工具执行前的多道闸门

6.1 是什么:Inspection 先于 Permission,Permission 先于 Dispatch

goose 没有把“用户点了允许”当成完整安全模型。工具请求进入 ToolInspectionManager 后,会按顺序运行多个 ToolInspector,每个 inspector 给出 InspectionResultAllowDenyRequireApproval,外加 reason、confidence、inspector_name 和 finding_id。最终结果再与 PermissionInspector 的用户偏好合并。

flowchart LR
  Request[ToolRequest] --> Inspect[ToolInspectionManager]
  Inspect --> Permission[PermissionInspector\n默认/一次/永久]
  Inspect --> Injection[PromptInjectionScanner]
  Inspect --> Adversary[AdversaryInspector]
  Inspect --> Egress[EgressInspector]
  Permission --> Decision{合并决策}
  Injection --> Decision
  Adversary --> Decision
  Egress --> Decision
  Decision -->|Allow| Execute[dispatch_tool_call]
  Decision -->|RequireApproval| UI[ActionRequired → 用户]
  Decision -->|Deny| ToolError[拒绝 ToolResponse]

6.2 源码怎么做:四类检查器

PermissionInspector:用户偏好层

它把工具调用映射到默认、always allow、allow once、always deny、never allow 等等级,并可把工具 schema 的 annotations 应用到 provider。用户确认通过 ToolConfirmationRouter 回传;如果 provider 自己管理权限(PermissionRouting::ActionRequired),则先让 provider 处理,否则由 goose 的 router 唤醒等待中的 tool future。

PromptInjectionScanner:输入内容层

Scanner 只对 shell 类工具做重点扫描,同时扫描 command 和最近对话上下文。可以使用 pattern matcher,也可以可选接入 command/prompt classifier。工具文本和上下文 confidence 会合并,超过 SECURITY_PROMPT_THRESHOLD 才标记为 malicious。过大的输入如果存在未扫描尾部,会按“无法完整验证即按可疑处理”的策略抬高 confidence。

AdversaryInspector:策略审查层

它从 adversary.md 读取规则和需审查的工具,默认聚焦 shell。每个工具请求可以连同最近消息交给另一个 provider 做“攻击者视角”判断,得到 reason/confidence,再决定是否要求确认。规则可由工作区覆盖,适合组织级安全策略。

EgressInspector:出站数据层

它从 shell 文本中提取 URL、git remote、S3/GCS、scp/ssh、docker registry、package publish 等目的地,并识别 inbound/outbound 方向。重点不是阻止所有网络,而是把“这条命令会把什么数据送到哪里”变成可审计的安全事件。

6.3 为什么这样做:把安全判断做成可组合的负责任失败

ToolInspectionManager 一个 inspector 失败时会记录错误并继续运行其他 inspector;这避免某个可选分类器下线导致全部工具不可用。但真实执行仍由权限结果兜底,安全扩展可以独立增加而不修改 Agent Loop。

安全边界还有两条:

6.4 安全结论

goose 的安全模型是“确定性规则 + 可选 ML/LLM + 用户授权 + 审计事件”的叠加,而不是单点检测。它不声称能证明命令安全,而是尽量让风险在执行前显形、在执行后可追踪。

源码定位