从零实现 GeekAgent —— Day8 权限与回滚

💡 原文中文,约11800字,阅读约需28分钟。
📝

内容提要

本文介绍从零实现GeekAgent的第八天,重点添加权限控制与回滚功能。通过`.geekagent/GeekAgent.json`配置文件为每个工具设定allow/ask/deny策略,未知工具默认拒绝;实现目录隔离防止路径越界和符号链接攻击;统一脱敏敏感环境变量;为文件写入保存最近状态,支持`/undo`恢复。代码净增155行,验证通过后,下一步将实现任务规划与子Agent。

🔎

延伸解读

权限策略的粒度与默认安全

本文通过 allow/ask/deny 三种策略为每个工具设置权限,未知工具默认拒绝,配置错误时启动失败而非静默放宽。这种设计将权限决策从工具实现中剥离,使得同一工具在不同项目中可以有不同的策略,例如 run_shell 在代码阅读项目中可设为 deny。默认拒绝未知工具的策略避免了新增工具时因忘记配置而自动获得权限的风险,体现了安全优先的原则。

路径安全的双重校验

safePath 不仅检查路径字符串是否越界,还通过 realpath 解析符号链接,防止通过项目内的符号链接访问外部目录。对于新文件,会逐级向上查找第一个存在的父目录进行真实路径校验。glob 则采用更严格的规则,只接受不含 .. 的相对模式,并将搜索根目录固定为配置根目录。这种双重校验机制有效防止了路径穿越攻击。

撤销功能的局限与设计取舍

撤销功能只保留最近一次写入的状态,且仅针对文件写入操作,不覆盖 shell 命令造成的文件变化。恢复时路径会重新经过安全校验,防止恶意篡改撤销文件导致越界写入。成功恢复后立即删除快照,避免重复撤销。这种设计优先解决最直接的问题,但明确不支持多步撤销和重做,适合快速回退刚发生的错误写入。

Q&A

GeekAgent 的权限配置支持哪三种策略?

GeekAgent 的权限配置支持 allow、ask、deny 三种策略。allow 表示直接执行,ask 表示需要用户确认,deny 表示拒绝执行。

GeekAgent 如何防止路径越界和符号链接攻击?

GeekAgent 通过 safePath 函数进行双重检查:先用 resolve 和 relative 检查路径字符串是否越界,再用 realpath 检查真实磁盘位置,防止符号链接指向根目录之外。对于 glob,只接受不含 .. 的相对模式,并固定以根目录为 cwd。

GeekAgent 如何实现敏感信息脱敏?

GeekAgent 在工具执行的统一出口调用 redact 函数,该函数会遍历环境变量,将名字包含 KEY、TOKEN、SECRET、PASSWORD 的变量值替换为 [REDACTED:变量名],从而避免敏感信息泄露到模型或终端。

GeekAgent 的 /undo 命令是如何工作的?

/undo 命令会读取 .geekagent/undo.json 文件,该文件保存了最近一次文件写入前的状态。如果文件原先不存在,则删除该文件;如果存在,则恢复其内容。恢复成功后,撤销记录会被删除,避免重复撤销。

GeekAgent 的权限配置中,未知工具默认是什么策略?

未知工具默认是 deny 策略,即拒绝执行。这样可以避免新增工具时忘记配置而自动获得权限。

GeekAgent 的撤销记录保存在哪里?

撤销记录保存在 .geekagent/undo.json 文件中,该文件只保留最近一次写入的状态,下一次写入会覆盖之前的记录。

GeekAgent 的权限配置中,root 字段的作用是什么?

root 字段定义了权限根目录,所有文件操作必须在该目录内进行。root 是相对于配置文件所在目录解析的,例如配置中的 ".." 指向项目根目录。

GeekAgent 的权限配置中,如果配置写错了会怎样?

如果配置写错了,程序会启动失败并报错,不会静默放宽权限。例如,root 必须是非空字符串,tools 必须是对象,每个工具的策略必须是 ask、allow 或 deny。

🏷️

标签

➡️

继续阅读