OpenClaw File Transfer 插件深度指南:节点文件读取、目录归档传输与授权策略迁移
2026/9/15 12:52:25 网站建设 项目流程

OpenClaw File Transfer 插件深度指南:节点文件读取、目录归档传输与授权策略迁移

【免费下载链接】openclawThe AI that really does things. Any OS. Any Platform. The lobster way. 🦞项目地址: https://gitcode.com/GitHub_Trending/cl/openclaw

File Transfer 是 OpenClaw 内置的文件传输插件(包名@openclaw/file-transfer),它通过专用 node 命令让 Agent 在已配对节点上读取文件、列出目录、打包拉取整个目录树并写入文件,从而绕过 bash stdout 截断限制。本文以 File Transfer 插件参考文档 为主体,结合插件源码与 CLI 参考,完整讲解四个工具的参数、默认值、授权策略模型、目录归档行为,以及升级后的权限迁移命令,帮助你完成插件的安装、配置、审计与安全加固。

插件概览:四个工具、一条 CLI、一种策略

从插件清单 openclaw.plugin.json 可以看到插件的核心契约:

维度内容
插件 IDfile-transfer
包名@openclaw/file-transfer
安装方式OpenClaw 内置(enabledByDefault: trueonStartup激活)
CLI 命令openclaw file-transfer(含子命令approvals migrate
契约类型tools,暴露file_fetchdir_listdir_fetchfile_write四个工具
分类documents-files

这四个工具彼此独立可选:允许其中一个并不会让其他工具自动可用,node 命令与路径策略仍然分别生效(详见 节点文件传输)。

插件入口 extensions/file-transfer/index.ts 在register()中完成四件事:

  1. 注册 CLI 命令组file-transfer
  2. 注册 node invoke 策略(registerNodeInvokePolicy),这是所有授权检查的入口;
  3. 注册四个 Agent 工具,全部通过createLazyTool懒加载,首次调用才真正import对应实现,降低启动开销;
  4. 注册四个节点宿主命令file.fetchdir.listdir.fetchfile.write,均标记cap: "file"dangerous: true,走node.invoke通道执行。

核心设计理念是:文件字节通过 base64 编码后经node.invoke传输,从而绕过 bash stdout 对二进制输出的截断,单个往返可承载最大 16 MB 的二进制数据(见 descriptors.ts 中FILE_FETCH_HARD_MAX_BYTES = 16 * 1024 * 1024)。

默认拒绝:路径授权策略模型

插件的默认行为是DENY(默认拒绝)。操作者必须在配置文件(~/.openclaw/openclaw.json)的plugins.entries.file-transfer.config.nodes下显式添加策略块,否则所有文件操作在到达节点前就会被拒绝(见 policy.ts 顶部注释)。

完整配置模板如下:

{ "plugins": { "entries": { "file-transfer": { "config": { "nodes": { "<nodeId-or-displayName>": { "ask": "off", "allowReadPaths": ["~/Screenshots/**", "/tmp/**"], "allowWritePaths": ["~/Downloads/**"], "denyPaths": ["**/.ssh/**", "**/.aws/**"], "maxBytes": 16777216, "followSymlinks": false }, "*": { "ask": "on-miss" } } } } } } }

节点级配置项

配置项类型默认值含义
ask"off" \| "on-miss" \| "always""off"询问模式(见下文)
allowReadPathsstring[]允许读取的路径 glob 列表
allowWritePathsstring[]允许写入的路径 glob 列表
denyPathsstring[]硬拒绝的路径 glob,永远优先
maxBytesnumber无(取工具默认值)单次传输的字节上限
followSymlinksbooleanfalse是否允许跟随符号链接

ask 三种模式

  • off:静默模式(当前默认)——匹配即允许,不匹配即拒绝;
  • on-miss:匹配则静默允许;未匹配时弹出提示征求操作者批准;
  • always:每次调用都提示操作者(denyPaths仍然硬拒绝)。

策略匹配时支持~展开(~/Downloads/**会展开为当前用户主目录),并且节点选择支持按nodeIddisplayName或通配符"*"匹配(见 policy.ts 的resolveNodePolicy)。

评估顺序(源码级)

policy.ts 中evaluateFilePolicyInternal的执行顺序,是理解授权行为的关键:

  1. 原始路径含..段 → 直接拒绝:检查的是未归一化的原始字符串,防止/allowed/../etc/passwd这类字面穿越序列先匹配到/allowed/**导致字节在 realpath 事后检查前就跨过节点边界;
  2. 没有任何nodes配置 →NO_POLICY(拒绝且不可询问,因为操作者根本没启用);
  3. 存在旧版正向权限且policyVersion不是 2 →POLICY_MIGRATION_REQUIRED(拒绝,提示运行迁移命令);
  4. denyPaths命中 →POLICY_DENIED(硬拒绝,不可询问);
  5. ask: always→ 每次都询问;
  6. allowReadPaths/allowWritePaths命中 → 静默允许(matched-allow);
  7. literalGrants(精确授权记录,见下文)命中 → 允许(matched-literal),并携带期望的 canonical path 供节点侧校验;
  8. ask: on-miss未命中 → 可询问的拒绝;
  9. 其余情况 → 硬拒绝。

精确授权(literalGrants)与符号链接防护

除操作者手写的 glob 外,策略还保存一种精确授权记录literalGrants):每次操作者批准一次调用后,系统会记录完整的四元组——稳定的节点 ID、命令、请求路径、以及节点权威的 canonical 路径(policy.ts 的persistLiteralGrant)。这些字符串是节点侧的不透明路径,Gateway 不会对其做归一化或喂给 glob 匹配器。

followSymlinks(默认false)提供了符号链接防护:节点侧 handler 会在任何 I/O之前对请求路径(新文件写入则对其父目录)执行 realpath,若与请求路径不一致则返回SYMLINK_REDIRECT拒绝。这能阻止用户可控目录中的符号链接(如~/Downloads/evil → /etc)把看似允许的路径重定向到被禁止的 canonical 位置。在 macOS 上/var → /private/var会误伤/var/folders路径时,可显式设为true恢复"跟随 + 事后校验"的宽松行为。

四个工具详解

所有工具的参数 schema 定义在 descriptors.ts,以下参数均来自该文件。node参数接受已配对节点的 ID、显示名或 IP(由nodes status展示),不接受localhostgatewayauto等关键字——本地工作区文件请使用本地 file/exec 工具。

file_fetch:拉取单个文件

从配对节点按绝对路径读取文件,全部字节存入 Gateway 的 file-transfer 媒体库,返回localPathmediaId。支持图片以 image content block 返回,小文本文件(≤8 KB)以内联方式返回。典型用途:截图、照片、收据、日志、源代码。

参数说明
node已配对节点 ID / 显示名 / IP
path节点上的绝对路径,服务端做 canonicalize
maxBytes最大读取字节数,默认 8 MB,硬上限 16 MB(单次往返)
gatewayUrl/gatewayToken可选,指定 Gateway 连接
timeoutMs可选超时

读取到的mediaId可复用作file_writesourceMediaId做二进制拷贝(要求节点具备写入能力)。

dir_list:目录列表

从配对节点获取目录列表(非本地工作区)。文本输出限制为 8192 UTF-8 字节,展示完整文件名、isDir标记与(可表示时的)文件大小;完整元数据保留在结构化 details 中。适合先发现远端路径,再决定读取哪些文件。

参数说明
node已配对节点
path节点上的目录绝对路径
pageToken分页令牌;来自上一次dir_list调用的文本nextPageToken,配合相同的 node 和 path 使用
maxEntries每页最大条目数,默认 200,硬上限 5000

分页有讲究:文本分页令牌(text 的nextPageToken)与结构化令牌可能不同,传入文本nextPageToken会从最后一个已展示条目之后继续;若第一个条目就无法表示,工具会明确报告"分页无法推进"。

dir_fetch:整目录归档拉取

将配对节点的**整个目录树(含 dotfiles 与隐藏目录)**打包为 gzip tar 归档后在 Gateway 解包。文本输出限制 8192 字节,展示rootDir、总fileCount及一段完整的relPath+ size 记录前缀;完整清单与附件元数据保留在结构化 details 中。没有分页机制,超过 16 MB(压缩后)的树会被拒绝。

参数说明
node已配对节点
path节点上的目录绝对路径
maxBytes最大 gzip tar 字节数,默认 8 MB,硬上限 16 MB
gatewayUrl/gatewayToken/timeoutMs可选

file_write:写入文件

向配对节点按绝对路径写入文件字节。采用原子写入(临时文件 + rename),默认拒绝覆盖(overwrite: true才替换),默认拒绝通过符号链接目标写入(除非策略显式允许跟随符号链接)。

参数说明
node已配对节点
path节点上的写入绝对路径
contentBase64内联字节(base64),解码后最大 16 MB
sourceMediaId复用之前file_fetch保存在媒体库中的mediaId不是本地路径,也不是其他媒体库的 ID),用于二进制拷贝
mimeType内容类型提示,不校验
overwrite是否允许覆盖已有文件,默认false
createParents是否创建缺失的父目录(等价mkdir -p),默认false

目录归档传输的边界行为

节点文件传输 对dir_fetch的归档安全做了详细说明,要点如下:

  • 逐后代策略检查:file-transfer 策略会检查源树的每一个后代,包括隐式目录(归档未包含目录头时也会检查父路径);任一后代被拒绝则整个传输被拒绝,而不是过滤掉该项。5000 后代上限包含这些隐式目录,共享父路径只计一次;
  • 同一解析器:归档成员身份由与解包相同的受限解析器与策略规划器校验,不使用人可读的tar列表——这样 Unicode 与换行文件名能保留精确拼写,生产方附加的 AppleDouble 文件会被检查而非隐藏;
  • 严格校验仍然生效:canonical 源路径/设备/inode 绑定、字节数与 SHA-256 校验、链接/穿越/碰撞检查、解包限制全部保留;畸形归档头与目标平台不允许的文件名仍会拒绝,文件名不会被截断或"修复"以让归档通过
  • 输出落盘:每次成功的文件读取都会把字节存入 Gateway 的 file-transfer 媒体库并同时返回localPathmediaId(包括内联文本与图片);已读取文件会保留清洗过的文件名主干,媒体类型决定扩展名(如train.py被识别为纯文本会变成train.txt),并附加唯一后缀以区分重复读取。

CLI:openclaw file-transfer approvals migrate权限迁移

升级 OpenClaw 后,旧版正向文件传输权限(allowReadPaths/allowWritePaths中的条目)会保持不活跃,直到你逐一审查。拒绝规则、大小限制与符号链接设置在整个过程中继续生效(不会因迁移而暂时放开)。

命令形式与选项

openclaw file-transfer approvals migrate openclaw file-transfer approvals migrate --dry-run openclaw file-transfer approvals migrate --json
选项效果
--dry-run走完所有提示并打印计划,不写任何配置
--json以 JSON 输出未审查的权限后直接退出,不提示、不写配置

两个选项默认均为关闭(cli.ts)。

运行位置约束

迁移命令必须在 Gateway 主机的交互式终端中运行,因为它直接更新该主机的 file-transfer 策略(cli.ts):

  • gateway.moderemote时拒绝运行;
  • 当 OpenClaw 配置无效时拒绝运行,需先修复配置再重试。

交互式审查流程

命令逐条列出旧权限,每项显示为<node selector> · read|write · <path>,需要为每条选择一种结局:

选项行为
Require exact reapproval移除这条含歧义的权限;下次使用时弹窗询问一次,并记录精确的节点、命令、请求路径与 canonical 目标
Keep as an intentional wildcard保留该条目为操作者手写的 glob
Remove this permission直接删除这条正向权限

全部选择后,命令打印包含各结局数量的计划,以及降级提示(旧版 OpenClaw 无法读取迁移后的格式),在一次确认后才写入配置。写入成功后报告相邻配置文件备份(.bak)的路径,若无法校验备份也会明确说明(cli.ts)。

脚本化与非交互使用

--json不修改任何东西,适合放入健康检查或升级脚本:

场景输出退出码
没有需要审查的权限{"status":"ok","changed":false,"message":"No legacy permissions need review."}0
仍有权限待审查{"status":"needs-input","changed":false,"items":[...],"command":"openclaw file-transfer approvals migrate"}2

不带--json时,命令先检查是否有工作可做:非交互 shell 仅在仍有权限待审查时报错,并提示到终端重跑,而不是替每条权限猜测结局;非交互且无待审查项时打印同样的 no-work 消息并以 0 退出,因此重复的升级脚本可以保持安静(docs/cli/file-transfer.md)。

迁移结果与降级

迁移成功后写入新格式:policyVersion升为 2,选 "exact" 的条目进入pendingReapprovals(下一次使用时询问并记录完整四元组),选 "keep-glob" 的条目保留在allowReadPaths/allowWritePaths中(approvals-migration.ts)。

需要降级时:先还原迁移后报告的.bak文件,再启动旧版 OpenClaw——旧版无法读取迁移后的格式,还原备份同时也会恢复旧版权限语义。

底层实现原理速览

  • base64 单往返传输:二进制字节 base64 编码后经node.invoke传输,绕过 bash stdout 截断;8 MB 默认 / 16 MB 硬上限(单次往返)定义于 descriptors.ts;
  • 默认拒绝:无策略配置时每个调用都被拒绝,策略块必须写在plugins.entries.file-transfer.config.nodes下(policy.ts);
  • 字面..穿越拦截:匹配任何 allow/deny glob 之前先拒绝原始字符串中含..段的路径,Windows 反斜杠同样处理(policy.ts);
  • canonical 路径绑定:精确授权只在节点侧 canonical 路径校验通过后才持久化,符号链接默认在 I/O 前被 realpath 检查拦截(policy.ts);
  • 懒加载工具:四个工具首次调用才加载实现,控制启动成本(index.ts)。

相关文档

  • File Transfer 插件参考:本文主体来源;
  • CLI 参考:openclaw file-transfer:完整 flag 面与退出码;
  • 节点文件传输:目录归档边界、终端文件上传与媒体库细节。

【免费下载链接】openclawThe AI that really does things. Any OS. Any Platform. The lobster way. 🦞项目地址: https://gitcode.com/GitHub_Trending/cl/openclaw

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询