0
0

给 Agent 文件工具加路径沙箱时,我会先从 realpath 和 dry-run 开始

最近给一个桌面端 Agent 加文件整理能力时,我把第一版写得很克制:模型只能提出读写计划,真正落盘前必须经过路径沙箱。文件工具一旦接上真实工作区,风险不只来自模型幻觉,也来自用户输入里的相对路径、符号链接、拖拽文件和旧任务重试。

Agent 文件工具从输入、策略、路径解析、realpath、dry-run、审批、写入到审计的流程图

原创示意图:文件操作先进入路径沙箱和 dry-run 计划,审批通过后再写入并留下审计记录。 来源:Codex image generation

问题背景

这个 Agent 会帮用户整理 Markdown、生成配置片段、移动导出文件。早期方案让模型直接返回目标路径,主进程再执行写入。看起来链路很短,实际调试时很快遇到两个问题:一个是 ../ 这类路径逃逸难以在日志里看清,另一个是 Windows 下分隔符、盘符和快捷入口会让简单字符串判断失效。

Node.js 的 path.resolve 文档说明,它会把一组路径片段解析成绝对路径,并做规范化处理;同一份文档也提醒,path.isAbsolute 只判断字面路径是否绝对,不能用来缓解路径遍历。OWASP 对 Path Traversal 的描述更直接:攻击者可能通过 ../ 序列或绝对路径访问授权目录之外的文件。这些资料让我把重点放到边界校验,prompt 里的约束只作为辅助。

踩坑和关键难点

第一个坑是只做 startsWith(workspaceRoot)。如果没有先规范化,project/../secret 这类输入可能绕过肉眼检查;如果只看字符串前缀,C:\workC:\workspace-old 也容易产生误判。第二个坑是符号链接和 junction。用户拖进工作区里的目录,表面上在项目内,真实落点可能指向外部位置,所以只看展示路径不够。

Electron 场景还多了一层 IPC 边界。官方安全清单强调,不要给加载远程内容的 renderer 开 Node.js integration,并且要校验所有 IPC 消息的 sender。我的结论是:renderer 只负责发起意图和展示 dry-run,文件路径决策必须在 main process 或受控服务里完成。

解决思路

我把文件工具协议拆成三层。第一层是 scope,模型只能选择 workspaceexportsnotes 这类预定义范围,不能提交完整根路径。第二层是 plan,模型描述相对路径、动作、原因和预期 diff。第三层是 commit,只有用户确认后的计划才能进入真实写入,并且写入时重新做一次路径校验。

路径沙箱的核心顺序是:先用 scope 找到根目录,再用 path.resolve(root, relativePath) 得到候选绝对路径,随后用 path.relative(root, candidate) 判断候选是否仍在根内。对已存在的文件使用 fs.promises.realpath 取真实位置;对新文件,先找最近存在的父目录并校验 realpath。Node.js 的 fsPromises.realpath 文档说明,它会解析路径的实际位置,这一步能把符号链接问题暴露出来。

关键步骤

落地时我会把每次工具调用写成一张计划卡:动作是 read、write、rename 还是 delete,目标相对路径是什么,命中了哪个 scope,预计新增或删除多少字节,是否触碰敏感扩展名。只要候选路径越界、父目录 realpath 越界、文件大小超限或扩展名不在允许列表里,计划卡就进入 blocked 状态,页面只展示原因,不提供继续按钮。

真正写入前还有两件事。第一是 dry-run 必须可读,用户能看到将要创建、覆盖、移动或删除的文件。第二是 commit 必须带 idempotencyKeyplanHash,避免页面重试、后台恢复或用户双击导致重复写入。写入完成后,审计日志记录 scope、相对路径、realpath 摘要、审批人、时间和结果,不记录完整敏感内容。

可复用经验

Agent 文件工具的安全感来自窄协议和可回放证据。模型适合生成意图和解释原因,路径边界、真实路径解析、权限判断和最终写入要交给确定性代码。这个模式也适合 RAG 导入、Electron 日志导出、批量 README 修正和本地自动化脚本生成。只要先把 scope、realpath、dry-run、审批和审计这五个点固定下来,后续再增加新文件动作时,风险会更容易评估。

主要来源

Node.js Path API: https://nodejs.org/api/path.html#pathresolvepaths

Node.js File System realpath: https://nodejs.org/api/fs.html#fspromisesrealpathpath-options

Electron Security: https://www.electronjs.org/docs/latest/tutorial/security

OWASP Path Traversal: https://owasp.org/www-community/attacks/Path_Traversal

评论