diff --git a/docs/zh-CN/gateway/security/index.md b/docs/zh-CN/gateway/security/index.md index 19ee51078..641e10f52 100644 --- a/docs/zh-CN/gateway/security/index.md +++ b/docs/zh-CN/gateway/security/index.md @@ -1,36 +1,35 @@ --- read_when: - - 添加会扩大访问权限或自动化范围的功能 -summary: 运行具备 shell 访问权限的 AI Gateway 网关时的安全注意事项和威胁模型 + - 添加会扩大访问范围或自动化能力的功能 +summary: 运行具有 shell 访问权限的 AI Gateway 网关时的安全考量和威胁模型 title: 安全 x-i18n: - generated_at: "2026-04-30T19:53:06Z" + generated_at: "2026-05-01T21:07:34Z" model: gpt-5.5 provider: openai - source_hash: 20cc63aa79aff1ec42a9c1a10037b11ad5dcc1a3a23d9e76842d4ffd9a920ad7 + source_hash: 03166be4bf491388e79cff5ed580091f6d27775838e53cb96ada0065c875fa5f source_path: gateway/security/index.md workflow: 16 --- - **个人助手信任模型。** 本指南假定每个 Gateway 网关有一个可信 - 操作者边界(单用户、个人助手模型)。 - OpenClaw **不是**适用于多个 - 对抗性用户共享一个智能体或 Gateway 网关的敌对多租户安全边界。如果你需要混合信任或 - 对抗性用户操作,请拆分信任边界(单独的 Gateway 网关 + - 凭证,最好还有单独的 OS 用户或主机)。 + **个人助理信任模型。** 本指南假设每个 Gateway 网关只有一个受信任的 + 操作员边界(单用户、个人助理模型)。 + OpenClaw **不是** 面向多个对抗性用户共享同一个智能体或 Gateway 网关的敌意多租户安全边界。 + 如果你需要混合信任或对抗性用户运行,请拆分信任边界(单独的 Gateway 网关 + + 凭证,理想情况下还要使用单独的 OS 用户或主机)。 -## 先确定范围:个人助手安全模型 +## 先确定范围:个人助理安全模型 -OpenClaw 安全指南假定采用**个人助手**部署:一个可信操作者边界,可能有多个智能体。 +OpenClaw 安全指南假设采用 **个人助理** 部署:一个受信任的操作员边界,可能有多个智能体。 -- 支持的安全姿态:每个 Gateway 网关一个用户/信任边界(建议每个边界一个 OS 用户/主机/VPS)。 -- 不支持的安全边界:由互不信任或对抗性用户使用的一个共享 Gateway 网关/智能体。 -- 如果需要对抗性用户隔离,请按信任边界拆分(单独的 Gateway 网关 + 凭证,最好还有单独的 OS 用户/主机)。 -- 如果多个不受信任的用户可以向一个启用工具的智能体发消息,请将他们视为共享该智能体的同一委托工具权限。 +- 支持的安全态势:每个 Gateway 网关一个用户/信任边界(建议每个边界使用一个 OS 用户/主机/VPS)。 +- 不支持的安全边界:由互不信任或对抗性用户使用的共享 Gateway 网关/智能体。 +- 如果需要对抗性用户隔离,请按信任边界拆分(单独的 Gateway 网关 + 凭证,理想情况下还要使用单独的 OS 用户/主机)。 +- 如果多个不受信任的用户可以向一个启用工具的智能体发消息,请将他们视为共享该智能体的同一组委托工具权限。 -本页说明如何在**该模型内**进行加固。它不声称能在一个共享 Gateway 网关上提供敌对多租户隔离。 +本页说明如何在 **该模型内** 加固。它并不声称在一个共享 Gateway 网关上提供敌意多租户隔离。 ## 快速检查:`openclaw security audit` @@ -45,119 +44,113 @@ openclaw security audit --fix openclaw security audit --json ``` -`security audit --fix` 会刻意保持较窄范围:它会将常见的开放组 +`security audit --fix` 会有意保持窄范围:它会将常见的开放组 策略切换为允许列表,恢复 `logging.redactSensitive: "tools"`,收紧 状态/配置/包含文件权限,并且在 Windows 上运行时使用 Windows ACL 重置,而不是 POSIX `chmod`。 -它会标记常见陷阱(Gateway 网关认证暴露、浏览器控制暴露、提升权限允许列表、文件系统权限、宽松的 exec 审批,以及开放渠道工具暴露)。 +它会标记常见风险点(Gateway 网关认证暴露、浏览器控制暴露、提升权限允许列表、文件系统权限、宽松的 exec 审批,以及开放渠道工具暴露)。 -OpenClaw 既是产品,也是实验:你正在把前沿模型行为接入真实消息表面和真实工具。**不存在“完全安全”的设置。**目标是有意识地明确: +OpenClaw 既是产品,也是实验:你正在把前沿模型行为接入真实消息表面和真实工具。**不存在“完全安全”的设置。** 目标是有意识地决定: - 谁可以与你的机器人对话 -- 机器人允许在哪里执行操作 -- 机器人可以接触什么 +- 机器人被允许在哪里执行操作 +- 机器人可以触碰什么 -从仍能正常工作的最小访问权限开始,然后随着信心增加再扩大范围。 +从仍能工作的最小访问权限开始,然后在信心增加后再扩大范围。 ### 部署和主机信任 -OpenClaw 假定主机和配置边界是可信的: +OpenClaw 假设主机和配置边界是受信任的: -- 如果某人可以修改 Gateway 网关主机状态/配置(`~/.openclaw`,包括 `openclaw.json`),请将其视为可信操作者。 -- 为多个互不信任/对抗性操作者运行一个 Gateway 网关**不是推荐设置**。 +- 如果有人可以修改 Gateway 网关主机状态/配置(`~/.openclaw`,包括 `openclaw.json`),请将他们视为受信任的操作员。 +- 不建议为多个互不信任/对抗性的操作员运行同一个 Gateway 网关。 - 对于混合信任团队,请使用单独的 Gateway 网关拆分信任边界(或至少使用单独的 OS 用户/主机)。 -- 推荐默认值:每台机器/主机(或 VPS)一个用户,为该用户运行一个 Gateway 网关,并在该 Gateway 网关中运行一个或多个智能体。 -- 在一个 Gateway 网关实例内,经过认证的操作者访问属于可信控制平面角色,而不是按用户划分的租户角色。 +- 建议默认设置:每台机器/主机(或 VPS)一个用户,为该用户运行一个 Gateway 网关,并在该 Gateway 网关中运行一个或多个智能体。 +- 在一个 Gateway 网关实例内,已认证的操作员访问是受信任的控制平面角色,而不是按用户划分的租户角色。 - 会话标识符(`sessionKey`、会话 ID、标签)是路由选择器,不是授权令牌。 -- 如果多人可以向一个启用工具的智能体发消息,他们每个人都可以驱动同一组权限。按用户的会话/记忆隔离有助于隐私,但不会把共享智能体变成按用户授权的主机访问。 +- 如果几个人都可以向一个启用工具的智能体发消息,他们每个人都可以引导同一组权限。按用户隔离会话/记忆有助于隐私,但不会把共享智能体转换为按用户划分的主机授权。 ### 共享 Slack 工作区:真实风险 -如果“Slack 中的所有人都可以向机器人发消息”,核心风险就是委托工具权限: +如果“Slack 中的每个人都可以向机器人发消息”,核心风险就是委托工具权限: -- 任何允许的发送者都可以在智能体策略范围内诱导工具调用(`exec`、浏览器、网络/文件工具); -- 来自某个发送者的提示词/内容注入可能导致影响共享状态、设备或输出的操作; -- 如果一个共享智能体拥有敏感凭证/文件,任何允许的发送者都可能通过工具使用驱动数据外泄。 +- 任何被允许的发送者都可以在智能体策略内诱导工具调用(`exec`、浏览器、网络/文件工具); +- 来自某个发送者的提示/内容注入可能导致影响共享状态、设备或输出的操作; +- 如果一个共享智能体拥有敏感凭证/文件,任何被允许的发送者都可能通过工具使用来驱动外泄。 -团队工作流应使用配备最少工具的单独智能体/Gateway 网关;将个人数据智能体保持私有。 +团队工作流应使用配备最小工具集的单独智能体/Gateway 网关;包含个人数据的智能体应保持私有。 ### 公司共享智能体:可接受模式 -当使用该智能体的所有人都处于同一信任边界内(例如一个公司团队),且该智能体严格限定于业务范围时,这是可接受的。 +当使用该智能体的所有人都处于同一个信任边界(例如一个公司团队),并且该智能体严格限定在业务范围内时,这是可以接受的。 - 在专用机器/VM/容器上运行它; -- 为该运行时使用专用 OS 用户 + 专用浏览器/配置文件/账号; -- 不要将该运行时登录到个人 Apple/Google 账号,或个人密码管理器/浏览器配置文件。 +- 为该运行时使用专用 OS 用户 + 专用浏览器/配置文件/账户; +- 不要让该运行时登录个人 Apple/Google 账户或个人密码管理器/浏览器配置文件。 -如果你在同一运行时混合个人和公司身份,就会破坏这种隔离,并增加个人数据暴露风险。 +如果你在同一运行时混用个人身份和公司身份,就会破坏分离并增加个人数据暴露风险。 ## Gateway 网关和节点信任概念 -将 Gateway 网关和节点视为一个操作者信任域,但角色不同: +将 Gateway 网关和节点视为同一个操作员信任域,但角色不同: - **Gateway 网关** 是控制平面和策略表面(`gateway.auth`、工具策略、路由)。 - **节点** 是与该 Gateway 网关配对的远程执行表面(命令、设备操作、主机本地能力)。 -- 通过 Gateway 网关认证的调用方在 Gateway 网关范围内受信任。配对后,节点操作会被视为该节点上的可信操作者操作。 -- 使用共享 Gateway 网关 - 令牌/密码认证的直接 local loopback 后端客户端可以发起内部控制平面 RPC,而无需呈现用户 - 设备身份。这不是远程或浏览器配对绕过:网络 - 客户端、节点客户端、设备令牌客户端和显式设备身份 +- 认证到 Gateway 网关的调用方在 Gateway 网关范围内受信任。配对后,节点操作是该节点上的受信任操作员操作。 +- 使用共享 Gateway 网关令牌/密码认证的直接 loopback 后端客户端可以在不提供用户 + 设备身份的情况下发起内部控制平面 RPC。这不是远程或浏览器配对绕过:网络 + 客户端、节点客户端、设备令牌客户端以及显式设备身份 仍会经过配对和范围升级强制检查。 - `sessionKey` 是路由/上下文选择,不是按用户认证。 -- Exec 审批(允许列表 + 询问)是操作者意图的防护栏,不是敌对多租户隔离。 -- OpenClaw 面向可信单操作者设置的产品默认值是,`gateway`/`node` 上的主机 exec 无需审批提示即可允许(`security="full"`,`ask="off"`,除非你收紧它)。该默认值是有意的用户体验设计,本身不是漏洞。 -- Exec 审批会绑定精确的请求上下文和尽力而为的直接本地文件操作数;它们不会从语义上建模每一种运行时/解释器加载器路径。需要强边界时,请使用沙箱隔离和主机隔离。 +- Exec 审批(允许列表 + 询问)是操作员意图的防护栏,而不是敌意多租户隔离。 +- OpenClaw 对受信任单操作员设置的产品默认值是,允许在 `gateway`/`node` 上进行主机 exec,且不显示审批提示(`security="full"`,`ask="off"`,除非你收紧它)。该默认值是有意的 UX,并不本身构成漏洞。 +- Exec 审批会绑定确切的请求上下文和尽力识别的直接本地文件操作数;它们不会从语义上建模每一个运行时/解释器加载器路径。若需要强边界,请使用沙箱隔离和主机隔离。 -如果你需要敌对用户隔离,请按 OS 用户/主机拆分信任边界并运行单独的 Gateway 网关。 +如果你需要敌意用户隔离,请按 OS 用户/主机拆分信任边界,并运行单独的 Gateway 网关。 ## 信任边界矩阵 -排查风险时可将其作为快速模型: +评估风险时,可将其作为快速模型: -| 边界或控制项 | 含义 | 常见误读 | -| --------------------------------------------------------- | ------------------------------------------------- | ----------------------------------------------------------------------------- | -| `gateway.auth`(令牌/密码/可信代理/设备认证) | 对 Gateway 网关 API 的调用方进行认证 | “每个帧都需要按消息签名才安全” | -| `sessionKey` | 用于上下文/会话选择的路由键 | “会话键是用户认证边界” | -| 提示词/内容防护栏 | 降低模型滥用风险 | “仅凭提示词注入就证明认证绕过” | -| `canvas.eval` / 浏览器 evaluate | 启用时属于有意提供的操作者能力 | “任何 JS eval 原语在此信任模型中都会自动成为漏洞” | -| 本地 TUI `!` shell | 由操作者显式触发的本地执行 | “本地 shell 便捷命令就是远程注入” | -| 节点配对和节点命令 | 已配对设备上的操作者级远程执行 | “远程设备控制默认应被视为不受信任用户访问” | -| `gateway.nodes.pairing.autoApproveCidrs` | 可选启用的可信网络节点注册策略 | “默认禁用的允许列表就是自动配对漏洞” | +| 边界或控制 | 含义 | 常见误读 | +| ----------------------------------------------------------- | ------------------------------------------------- | ----------------------------------------------------------------------------- | +| `gateway.auth`(令牌/密码/受信任代理/设备认证) | 对 Gateway 网关 API 的调用方进行认证 | “为了安全,每一帧都需要按消息签名” | +| `sessionKey` | 用于上下文/会话选择的路由键 | “会话键是用户认证边界” | +| 提示/内容防护栏 | 降低模型滥用风险 | “仅凭提示注入就证明认证绕过” | +| `canvas.eval` / 浏览器 evaluate | 启用时的有意操作员能力 | “任何 JS eval 原语在此信任模型中都会自动成为漏洞” | +| 本地 TUI `!` shell | 由操作员显式触发的本地执行 | “本地 shell 便利命令是远程注入” | +| 节点配对和节点命令 | 在已配对设备上的操作员级远程执行 | “默认应将远程设备控制视为不受信任用户访问” | +| `gateway.nodes.pairing.autoApproveCidrs` | 选择启用的受信任网络节点注册策略 | “默认禁用的允许列表是自动配对漏洞” | -## 按设计不属于漏洞 +## 设计上不属于漏洞 - + -这些模式经常被报告,通常会在未展示真实边界绕过时关闭且不采取操作: +这些模式经常被报告,通常会在未证明真实边界绕过的情况下关闭为无需处理: -- 仅提示词注入链,且不包含策略、认证或沙箱绕过。 -- 假设在一个共享主机或 - 配置上进行敌对多租户操作的声明。 -- 将正常操作者读取路径访问(例如 - `sessions.list` / `sessions.preview` / `chat.history`)在 - 共享 Gateway 网关设置中归类为 IDOR 的声明。 -- 仅限 localhost 部署的发现(例如仅 local loopback - Gateway 网关上的 HSTS)。 -- 针对此仓库中不存在的入站路径的 Discord 入站 webhook 签名发现。 +- 没有策略、认证或沙箱绕过的纯提示注入链。 +- 假设在一个共享主机或配置上运行敌意多租户的主张。 +- 将正常操作员读路径访问(例如 + `sessions.list` / `sessions.preview` / `chat.history`)在共享 Gateway 网关设置中归类为 IDOR 的主张。 +- 仅限 localhost 的部署发现(例如仅 loopback Gateway 网关上的 HSTS)。 +- 关于本仓库中不存在的入站路径的 Discord 入站 webhook 签名发现。 - 将节点配对元数据视为 `system.run` 的隐藏第二层按命令 - 审批,而真实执行边界仍然是 + 审批层的报告;实际上执行边界仍然是 Gateway 网关的全局节点命令策略加上节点自身的 exec - 审批的报告。 -- 将已配置的 `gateway.nodes.pairing.autoApproveCidrs` 本身视为 - 漏洞的报告。此设置默认禁用,需要 - 显式 CIDR/IP 条目,仅适用于首次 `role: node` 配对且 - 未请求范围的情况,并且不会自动批准操作者/浏览器/Control UI、 + 审批。 +- 将已配置的 `gateway.nodes.pairing.autoApproveCidrs` 本身视为漏洞的报告。 + 此设置默认禁用,需要显式 CIDR/IP 条目,只适用于第一次 + `role: node` 配对且没有请求的范围,并且不会自动批准操作员/浏览器/Control UI、 WebChat、角色升级、范围升级、元数据变更、公钥变更, - 或同主机 local loopback 可信代理头路径,除非已显式启用 local loopback 可信代理认证。 -- 将 `sessionKey` 视为 - 认证令牌的“缺少按用户授权”发现。 + 或同主机 loopback 受信任代理标头路径,除非已显式启用 loopback 受信任代理认证。 +- 将 `sessionKey` 视为认证令牌的“缺少按用户授权”发现。 ## 60 秒加固基线 -先使用此基线,然后按可信智能体选择性地重新启用工具: +先使用此基线,然后按受信任智能体选择性地重新启用工具: ```json5 { @@ -182,16 +175,16 @@ OpenClaw 假定主机和配置边界是可信的: } ``` -这会让 Gateway 网关仅限本地访问,隔离私信,并默认禁用控制平面/运行时工具。 +这会让 Gateway 网关保持仅本地访问,隔离私信,并默认禁用控制平面/运行时工具。 ## 共享收件箱快速规则 如果不止一个人可以私信你的机器人: -- 设置 `session.dmScope: "per-channel-peer"`(或对多账号渠道使用 `"per-account-channel-peer"`)。 +- 设置 `session.dmScope: "per-channel-peer"`(对于多账户渠道,设置为 `"per-account-channel-peer"`)。 - 保持 `dmPolicy: "pairing"` 或严格允许列表。 -- 绝不要将共享私信与宽泛工具访问结合使用。 -- 这会加固协作式/共享收件箱,但当用户共享主机/配置写入访问时,它并不是为敌对共租户隔离而设计的。 +- 切勿将共享私信与宽泛工具访问结合使用。 +- 这会加固协作式/共享收件箱,但当用户共享主机/配置写入访问时,并不设计为敌意共同租户隔离。 ## 上下文可见性模型 @@ -200,101 +193,106 @@ OpenClaw 区分两个概念: - **触发授权**:谁可以触发智能体(`dmPolicy`、`groupPolicy`、允许列表、提及门控)。 - **上下文可见性**:哪些补充上下文会注入模型输入(回复正文、引用文本、线程历史、转发元数据)。 -允许列表控制触发和命令授权。`contextVisibility` 设置控制补充上下文(引用回复、线程根、获取的历史)如何过滤: +允许列表会控制触发和命令授权。`contextVisibility` 设置控制如何过滤补充上下文(引用回复、线程根、抓取的历史): -- `contextVisibility: "all"`(默认)按收到的内容保留补充上下文。 -- `contextVisibility: "allowlist"` 将补充上下文过滤为通过当前允许列表检查的发送者。 -- `contextVisibility: "allowlist_quote"` 的行为类似 `allowlist`,但仍保留一个显式引用回复。 +- `contextVisibility: "all"`(默认)会按接收内容保留补充上下文。 +- `contextVisibility: "allowlist"` 会将补充上下文过滤为通过当前允许列表检查的发送者。 +- `contextVisibility: "allowlist_quote"` 的行为类似 `allowlist`,但仍会保留一条显式引用回复。 -按渠道或按房间/对话设置 `contextVisibility`。设置详情请参阅[群聊](/zh-CN/channels/groups#context-visibility-and-allowlists)。 +可按渠道或按房间/对话设置 `contextVisibility`。有关设置详情,请参阅[群聊](/zh-CN/channels/groups#context-visibility-and-allowlists)。 -安全通告排查指南: +咨询性分诊指南: -- 仅显示“模型可以看到来自非允许列表发送者的引用文本或历史文本”的报告属于可通过 `contextVisibility` 解决的加固发现,本身并不构成认证或沙箱边界绕过。 -- 要产生安全影响,报告仍需要证明存在信任边界绕过(认证、策略、沙箱、批准或另一个已记录的边界)。 +- 仅显示“模型可以看到来自非允许列表发送者的引用文本或历史文本”的说法,是可通过 `contextVisibility` 处理的加固发现,本身不是身份验证或沙箱边界绕过。 +- 若要产生安全影响,报告仍需证明存在信任边界绕过(身份验证、策略、沙箱、审批或其他已记录的边界)。 ## 审计检查内容(高层概览) - **入站访问**(私信策略、群组策略、允许列表):陌生人能否触发机器人? -- **工具影响范围**(高权限工具 + 开放房间):提示注入是否可能变成 shell、文件或网络操作? -- **Exec 批准漂移**(`security=full`、`autoAllowSkills`、未启用 `strictInlineEval` 的解释器允许列表):主机执行防护栏是否仍按你的预期工作? - - `security="full"` 是一种宽泛的态势警告,不是缺陷证明。它是受信任个人助手设置所选择的默认值;只有当你的威胁模型需要批准或允许列表防护栏时才收紧它。 -- **网络暴露**(Gateway 网关绑定/认证、Tailscale Serve/Funnel、弱/短认证令牌)。 +- **工具影响范围**(高权限工具 + 开放房间):提示注入是否可能转化为 shell、文件或网络操作? +- **执行审批漂移**(`security=full`、`autoAllowSkills`、未启用 `strictInlineEval` 的解释器允许列表):主机执行防护是否仍按你的预期工作? + - `security="full"` 是一种宽泛的姿态警告,不是 bug 证据。它是可信个人助手设置的默认选择;仅在你的威胁模型需要审批或允许列表防护时才收紧它。 +- **网络暴露**(Gateway 网关绑定/身份验证、Tailscale Serve/Funnel、弱/短身份验证令牌)。 - **浏览器控制暴露**(远程节点、中继端口、远程 CDP 端点)。 -- **本地磁盘卫生**(权限、符号链接、配置 include、“同步文件夹”路径)。 +- **本地磁盘卫生**(权限、符号链接、配置包含、“同步文件夹”路径)。 - **插件**(插件在没有显式允许列表的情况下加载)。 -- **策略漂移/配置错误**(配置了沙箱 Docker 设置但沙箱模式关闭;`gateway.nodes.denyCommands` 模式无效,因为匹配仅按精确命令名进行(例如 `system.run`),不会检查 shell 文本;危险的 `gateway.nodes.allowCommands` 条目;全局 `tools.profile="minimal"` 被按智能体配置覆盖;插件拥有的工具在宽松工具策略下可达)。 -- **运行时期望漂移**(例如假设隐式 exec 仍表示 `sandbox`,但 `tools.exec.host` 现在默认为 `auto`;或在沙箱模式关闭时显式设置 `tools.exec.host="sandbox"`)。 -- **模型卫生**(当配置的模型看起来像旧版模型时发出警告;不是硬性阻断)。 +- **策略漂移/错误配置**(配置了沙箱 Docker 设置但沙箱模式关闭;`gateway.nodes.denyCommands` 模式无效,因为匹配仅按精确命令名称进行(例如 `system.run`),不会检查 shell 文本;危险的 `gateway.nodes.allowCommands` 条目;全局 `tools.profile="minimal"` 被按智能体配置覆盖;插件拥有的工具在宽松工具策略下可访问)。 +- **运行时预期漂移**(例如假设隐式执行仍意味着 `sandbox`,而 `tools.exec.host` 现在默认是 `auto`;或在沙箱模式关闭时显式设置 `tools.exec.host="sandbox"`)。 +- **模型卫生**(在配置的模型看起来较旧时警告;不是硬性阻断)。 -如果运行 `--deep`,OpenClaw 还会尽最大努力尝试实时 Gateway 网关探测。 +如果运行 `--deep`,OpenClaw 还会尽力尝试进行实时 Gateway 网关探测。 ## 凭证存储映射 -在审计访问或决定备份内容时使用此映射: +在审计访问权限或决定备份内容时使用此信息: - **WhatsApp**:`~/.openclaw/credentials/whatsapp//creds.json` -- **Telegram 机器人令牌**:配置/环境,或 `channels.telegram.tokenFile`(仅限普通文件;拒绝符号链接) -- **Discord 机器人令牌**:配置/环境,或 SecretRef(env/file/exec 提供商) -- **Slack 令牌**:配置/环境(`channels.slack.*`) +- **Telegram 机器人令牌**:配置/环境变量或 `channels.telegram.tokenFile`(仅限常规文件;拒绝符号链接) +- **Discord 机器人令牌**:配置/环境变量或 SecretRef(env/file/exec 提供商) +- **Slack 令牌**:配置/环境变量(`channels.slack.*`) - **配对允许列表**: - `~/.openclaw/credentials/-allowFrom.json`(默认账户) - `~/.openclaw/credentials/--allowFrom.json`(非默认账户) -- **模型认证配置文件**:`~/.openclaw/agents//agent/auth-profiles.json` +- **模型身份验证配置文件**:`~/.openclaw/agents//agent/auth-profiles.json` - **Codex 运行时状态**:`~/.openclaw/agents//agent/codex-home/` -- **文件支持的密钥载荷(可选)**:`~/.openclaw/secrets.json` +- **文件后端密钥载荷(可选)**:`~/.openclaw/secrets.json` - **旧版 OAuth 导入**:`~/.openclaw/credentials/oauth.json` -## 安全审计清单 +## 安全审计检查清单 当审计输出发现时,按以下优先级处理: 1. **任何“开放”且启用工具的情况**:先锁定私信/群组(配对/允许列表),再收紧工具策略/沙箱隔离。 -2. **公共网络暴露**(LAN 绑定、Funnel、缺失认证):立即修复。 -3. **浏览器控制远程暴露**:按操作者访问处理(仅 tailnet、谨慎配对节点、避免公共暴露)。 -4. **权限**:确保状态/配置/凭证/认证不对组或所有用户可读。 +2. **公网暴露**(LAN 绑定、Funnel、缺少身份验证):立即修复。 +3. **浏览器控制远程暴露**:将其视为操作员访问权限(仅 tailnet、谨慎配对节点、避免公网暴露)。 +4. **权限**:确保状态/配置/凭证/身份验证文件不是组/全局可读。 5. **插件**:只加载你明确信任的内容。 -6. **模型选择**:对任何带工具的机器人,优先使用现代、经过指令加固的模型。 +6. **模型选择**:任何带工具的机器人都应优先使用现代、指令加固的模型。 ## 安全审计术语表 -每个审计发现都由结构化 `checkId` 标识(例如 +每个审计发现都由结构化的 `checkId` 标识(例如 `gateway.bind_no_auth` 或 `tools.exec.security_full_configured`)。常见 -critical 严重性类别: +严重等级类别: -- `fs.*` — 状态、配置、凭证、认证配置文件的文件系统权限。 -- `gateway.*` — 绑定模式、认证、Tailscale、Control UI、受信任代理设置。 -- `hooks.*`、`browser.*`、`sandbox.*`、`tools.exec.*` — 各个表面的加固。 -- `plugins.*`、`skills.*` — 插件/Skills 供应链和扫描发现。 -- `security.exposure.*` — 访问策略与工具影响范围交汇处的横向检查。 +- `fs.*` — 状态、配置、凭证、身份验证配置文件的文件系统权限。 +- `gateway.*` — 绑定模式、身份验证、Tailscale、Control UI、可信代理设置。 +- `hooks.*`、`browser.*`、`sandbox.*`、`tools.exec.*` — 各表面的加固。 +- `plugins.*`、`skills.*` — 插件/skill 供应链和扫描发现。 +- `security.exposure.*` — 访问策略与工具影响范围相交的横切检查。 -在 [安全审计检查](/zh-CN/gateway/security/audit-checks) 查看完整目录,包括严重性级别、修复键和自动修复支持。 +完整目录包含严重级别、修复键和自动修复支持,见 +[安全审计检查](/zh-CN/gateway/security/audit-checks)。 ## 通过 HTTP 使用 Control UI -Control UI 需要**安全上下文**(HTTPS 或 localhost)来生成设备身份。 -`gateway.controlUi.allowInsecureAuth` 是一个本地兼容性开关: +Control UI 需要**安全上下文**(HTTPS 或 localhost)来生成设备 +身份。`gateway.controlUi.allowInsecureAuth` 是本地兼容性开关: -- 在 localhost 上,当页面通过非安全 HTTP 加载时,它允许 Control UI 在没有设备身份的情况下认证。 +- 在 localhost 上,当页面通过非安全 HTTP 加载时,它允许 Control UI 身份验证不使用设备身份。 - 它不会绕过配对检查。 - 它不会放宽远程(非 localhost)设备身份要求。 -优先使用 HTTPS(Tailscale Serve),或在 `127.0.0.1` 上打开 UI。 +优先使用 HTTPS(Tailscale Serve)或在 `127.0.0.1` 打开 UI。 -仅限紧急兜底场景,`gateway.controlUi.dangerouslyDisableDeviceAuth` -会完全禁用设备身份检查。这是严重的安全降级;除非你正在主动调试并且能快速恢复,否则保持关闭。 +仅限应急场景,`gateway.controlUi.dangerouslyDisableDeviceAuth` +会完全禁用设备身份检查。这是严重的安全降级; +除非你正在主动调试并且可以快速恢复,否则保持关闭。 与这些危险标志分开,成功的 `gateway.auth.mode: "trusted-proxy"` -可以在没有设备身份的情况下接纳**操作者** Control UI 会话。这是有意的认证模式行为,不是 `allowInsecureAuth` 捷径,并且仍不会扩展到 node 角色的 Control UI 会话。 +可以在没有设备身份的情况下接纳**操作员** Control UI 会话。这是 +有意设计的身份验证模式行为,不是 `allowInsecureAuth` 捷径,并且它仍然 +不会扩展到节点角色的 Control UI 会话。 启用此设置时,`openclaw security audit` 会发出警告。 ## 不安全或危险标志摘要 -当已知的不安全/危险调试开关启用时,`openclaw security audit` 会提出 `config.insecure_or_dangerous_flags`。在生产环境中保持这些项未设置。 +当已知的不安全/危险调试开关被启用时,`openclaw security audit` 会引发 `config.insecure_or_dangerous_flags`。在 +生产环境中保持这些设置未设置。 - + - `gateway.controlUi.allowInsecureAuth=true` - `gateway.controlUi.dangerouslyAllowHostHeaderOriginFallback=true` - `gateway.controlUi.dangerouslyDisableDeviceAuth=true` @@ -305,15 +303,15 @@ Control UI 需要**安全上下文**(HTTPS 或 localhost)来生成设备身 - + Control UI 和浏览器: - `gateway.controlUi.dangerouslyAllowHostHeaderOriginFallback` - `gateway.controlUi.dangerouslyDisableDeviceAuth` - `browser.ssrfPolicy.dangerouslyAllowPrivateNetwork` - 渠道名称匹配(内置渠道和插件渠道;适用时也可按 - `accounts.` 配置): + 渠道名称匹配(内置渠道和插件渠道;在适用时也可按 + `accounts.` 使用): - `channels.discord.dangerouslyAllowNameMatching` - `channels.slack.dangerouslyAllowNameMatching` @@ -327,7 +325,7 @@ Control UI 需要**安全上下文**(HTTPS 或 localhost)来生成设备身 网络暴露: - - `channels.telegram.network.dangerouslyAllowPrivateNetwork`(也可按账户配置) + - `channels.telegram.network.dangerouslyAllowPrivateNetwork`(也可按账户设置) 沙箱 Docker(默认值 + 按智能体): @@ -341,15 +339,15 @@ Control UI 需要**安全上下文**(HTTPS 或 localhost)来生成设备身 ## 反向代理配置 如果你在反向代理(nginx、Caddy、Traefik 等)后运行 Gateway 网关,请配置 -`gateway.trustedProxies`,以便正确处理转发的客户端 IP。 +`gateway.trustedProxies`,以正确处理转发的客户端 IP。 -当 Gateway 网关从**不在** `trustedProxies` 中的地址检测到代理头时,它**不会**把连接视为本地客户端。如果 Gateway 网关认证已禁用,这些连接会被拒绝。这样可以防止认证绕过,否则被代理的连接可能看起来来自 localhost 并获得自动信任。 +当 Gateway 网关检测到来自**不在** `trustedProxies` 中的地址的代理标头时,它**不会**将连接视为本地客户端。如果禁用了 Gateway 网关身份验证,这些连接会被拒绝。这可以防止身份验证绕过,否则代理连接会看起来像来自 localhost 并获得自动信任。 -`gateway.trustedProxies` 也会供 `gateway.auth.mode: "trusted-proxy"` 使用,但该认证模式更严格: +`gateway.trustedProxies` 也会供给 `gateway.auth.mode: "trusted-proxy"`,但该身份验证模式更严格: -- trusted-proxy 认证默认会对回环来源代理**失败关闭** -- 同主机回环反向代理可以使用 `gateway.trustedProxies` 进行本地客户端检测和转发 IP 处理 -- 同主机回环反向代理只有在 `gateway.auth.trustedProxy.allowLoopback = true` 时才能满足 `gateway.auth.mode: "trusted-proxy"`;否则请使用令牌/密码认证 +- trusted-proxy 身份验证默认会对 loopback 来源代理**失败关闭** +- 同主机 loopback 反向代理可以使用 `gateway.trustedProxies` 进行本地客户端检测和转发 IP 处理 +- 同主机 loopback 反向代理只有在 `gateway.auth.trustedProxy.allowLoopback = true` 时才能满足 `gateway.auth.mode: "trusted-proxy"`;否则使用令牌/密码身份验证 ```yaml gateway: @@ -363,121 +361,125 @@ gateway: password: ${OPENCLAW_GATEWAY_PASSWORD} ``` -配置 `trustedProxies` 后,Gateway 网关使用 `X-Forwarded-For` 来确定客户端 IP。默认忽略 `X-Real-IP`,除非显式设置 `gateway.allowRealIpFallback: true`。 +配置 `trustedProxies` 后,Gateway 网关会使用 `X-Forwarded-For` 来确定客户端 IP。默认会忽略 `X-Real-IP`,除非显式设置了 `gateway.allowRealIpFallback: true`。 -受信任代理头不会让节点设备配对自动受信任。 -`gateway.nodes.pairing.autoApproveCidrs` 是独立的、默认禁用的 -操作者策略。即使启用,也会从节点自动批准中排除回环来源的受信任代理头路径,因为本地调用者可以伪造这些头,包括在显式启用回环 trusted-proxy 认证时也是如此。 +可信代理标头不会让节点设备配对自动受信任。 +`gateway.nodes.pairing.autoApproveCidrs` 是单独的、默认禁用的 +操作员策略。即使启用,loopback 来源可信代理标头路径 +也会排除在节点自动批准之外,因为本地调用者可以伪造这些 +标头,包括在显式启用 loopback trusted-proxy 身份验证时也是如此。 -良好的反向代理行为(覆盖传入的转发头): +良好的反向代理行为(覆盖传入转发标头): ```nginx proxy_set_header X-Forwarded-For $remote_addr; proxy_set_header X-Real-IP $remote_addr; ``` -不良的反向代理行为(追加/保留不受信任的转发头): +不良的反向代理行为(追加/保留不可信转发标头): ```nginx proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; ``` -## HSTS 和源站说明 +## HSTS 和来源说明 -- OpenClaw gateway 优先本地/回环。如果你在反向代理处终止 TLS,请在那里为面向代理的 HTTPS 域设置 HSTS。 -- 如果 gateway 自身终止 HTTPS,可以设置 `gateway.http.securityHeaders.strictTransportSecurity`,让 OpenClaw 响应发出 HSTS 头。 -- 详细部署指南位于 [受信任代理认证](/zh-CN/gateway/trusted-proxy-auth#tls-termination-and-hsts)。 -- 对于非回环 Control UI 部署,默认需要 `gateway.controlUi.allowedOrigins`。 -- `gateway.controlUi.allowedOrigins: ["*"]` 是显式允许所有浏览器源站的策略,不是加固默认值。避免在严格受控的本地测试之外使用它。 -- 即使启用通用回环豁免,回环上的浏览器源站认证失败仍会受到速率限制,但锁定键按规范化后的 `Origin` 值划分,而不是使用一个共享的 localhost 桶。 -- `gateway.controlUi.dangerouslyAllowHostHeaderOriginFallback=true` 会启用 Host 头源站回退模式;将其视为操作者选择的危险策略。 -- 将 DNS 重绑定和代理 Host 头行为视为部署加固事项;保持 `trustedProxies` 严格,避免将 gateway 直接暴露到公网。 +- OpenClaw gateway 优先用于本地/local loopback。如果你在反向代理处终止 TLS,请在那里对面向代理的 HTTPS 域名设置 HSTS。 +- 如果 gateway 本身终止 HTTPS,你可以设置 `gateway.http.securityHeaders.strictTransportSecurity`,让 OpenClaw 响应发出 HSTS 标头。 +- 详细部署指南见 [Trusted Proxy Auth](/zh-CN/gateway/trusted-proxy-auth#tls-termination-and-hsts)。 +- 对于非 loopback Control UI 部署,默认需要 `gateway.controlUi.allowedOrigins`。 +- `gateway.controlUi.allowedOrigins: ["*"]` 是显式允许所有浏览器来源策略,不是加固默认值。避免在严格受控的本地测试之外使用它。 +- 即使启用了通用 loopback 豁免,loopback 上的浏览器来源身份验证失败仍会受到速率限制,但锁定键按 + 规范化的 `Origin` 值作用域,而不是一个共享的 localhost 存储桶。 +- `gateway.controlUi.dangerouslyAllowHostHeaderOriginFallback=true` 启用 Host 标头来源回退模式;应将其视为操作员选择的危险策略。 +- 将 DNS rebinding 和代理主机标头行为视为部署加固问题;保持 `trustedProxies` 严格,并避免将 gateway 直接暴露到公网。 -## 本地会话日志存储在磁盘上 +## 本地会话日志保存在磁盘上 -OpenClaw 将会话转录存储在 `~/.openclaw/agents//sessions/*.jsonl` 下的磁盘上。 +OpenClaw 将会话转录存储在磁盘上的 `~/.openclaw/agents//sessions/*.jsonl` 下。 这是会话连续性和(可选)会话记忆索引所必需的,但也意味着 **任何拥有文件系统访问权限的进程/用户都可以读取这些日志**。将磁盘访问视为信任 边界,并锁定 `~/.openclaw` 的权限(见下面的审计部分)。如果你需要 -在智能体之间进行更强隔离,请使用不同的操作系统用户或不同主机运行它们。 +在智能体之间实现更强隔离,请让它们在不同的操作系统用户或不同主机下运行。 ## 节点执行(system.run) -如果配对了 macOS 节点,Gateway 网关可以在该节点上调用 `system.run`。这是在 Mac 上进行的**远程代码执行**: +如果已配对 macOS 节点,Gateway 网关可以在该节点上调用 `system.run`。这是 Mac 上的**远程代码执行**: - 需要节点配对(批准 + 令牌)。 -- Gateway 网关节点配对不是逐命令批准界面。它建立节点身份/信任并签发令牌。 +- Gateway 网关节点配对不是按命令批准的界面。它建立节点身份/信任并签发令牌。 - Gateway 网关通过 `gateway.nodes.allowCommands` / `denyCommands` 应用粗粒度的全局节点命令策略。 -- 在 Mac 上通过 **设置 → Exec 批准**(安全 + 询问 + 允许列表)控制。 -- 逐节点 `system.run` 策略是节点自己的 exec 批准文件(`exec.approvals.node.*`),它可以比 Gateway 网关的全局命令 ID 策略更严格或更宽松。 -- 以 `security="full"` 和 `ask="off"` 运行的节点遵循默认的受信任操作员模型。除非你的部署明确要求更严格的批准或允许列表立场,否则应将其视为预期行为。 -- 批准模式绑定精确的请求上下文,并在可能时绑定一个具体的本地脚本/文件操作数。如果 OpenClaw 无法为解释器/运行时命令准确识别一个直接本地文件,则拒绝基于批准的执行,而不是承诺完整的语义覆盖。 +- 在 Mac 上通过 **设置 → 执行批准** 控制(安全 + 询问 + 允许列表)。 +- 按节点的 `system.run` 策略是节点自己的执行批准文件(`exec.approvals.node.*`),它可以比 Gateway 网关的全局命令 ID 策略更严格或更宽松。 +- 以 `security="full"` 和 `ask="off"` 运行的节点遵循默认的可信操作员模型。除非你的部署明确要求更严格的批准或允许列表立场,否则应将其视为预期行为。 +- 批准模式会绑定精确的请求上下文,并在可能时绑定一个具体的本地脚本/文件操作数。如果 OpenClaw 无法为解释器/运行时命令准确识别一个直接本地文件,则会拒绝基于批准的执行,而不是承诺完整的语义覆盖。 - 对于 `host=node`,基于批准的运行还会存储一个规范化的已准备 `systemRunPlan`;后续已批准的转发会复用该存储计划,并且 Gateway 网关 验证会拒绝调用方在批准请求创建后对命令/cwd/会话上下文的编辑。 -- 如果你不想要远程执行,请将安全设置为 **deny**,并移除此 Mac 的节点配对。 +- 如果你不想启用远程执行,请将安全性设置为 **deny**,并移除该 Mac 的节点配对。 -这个区别对分诊很重要: +这一区分对分诊很重要: -- 重新连接的已配对节点通告不同的命令列表,本身并不是漏洞,只要 Gateway 网关全局策略和节点的本地 exec 批准仍然执行实际的执行边界。 -- 将节点配对元数据视为第二个隐藏的逐命令批准层的报告,通常是策略/用户体验混淆,而不是安全边界绕过。 +- 已配对节点重新连接并宣告不同的命令列表,本身并不是漏洞,前提是 Gateway 网关全局策略和节点的本地执行批准仍然强制执行实际的执行边界。 +- 将节点配对元数据当作第二层隐藏的按命令批准层的报告,通常是策略/UX 混淆,而不是安全边界绕过。 ## 动态 Skills(监视器 / 远程节点) OpenClaw 可以在会话中刷新 Skills 列表: -- **Skills 监视器**:对 `SKILL.md` 的更改可以在下一次智能体回合更新 Skills 快照。 +- **Skills 监视器**:对 `SKILL.md` 的更改可以在下一次智能体轮次更新 Skills 快照。 - **远程节点**:连接 macOS 节点可以让仅限 macOS 的 Skills 符合条件(基于二进制探测)。 -将 Skills 文件夹视为 **受信任代码**,并限制谁可以修改它们。 +请将 Skills 文件夹视为 **可信代码**,并限制可修改它们的人员。 ## 威胁模型 你的 AI 助手可以: - 执行任意 shell 命令 -- 读取/写入文件 +- 读/写文件 - 访问网络服务 -- 向任何人发送消息(如果你给它 WhatsApp 访问权限) +- 向任何人发送消息(如果你授予它 WhatsApp 访问权限) 给你发消息的人可以: -- 试图诱骗你的 AI 做坏事 -- 通过社交工程获取你的数据访问权限 -- 探测基础设施细节 +- 试图诱导你的 AI 做坏事 +- 通过社会工程获取你的数据访问权 +- 探测基础设施详情 -## 核心概念:智能之前先做访问控制 +## 核心概念:先做访问控制,再谈智能 -这里的大多数失败都不是复杂漏洞,而是“有人给机器人发了消息,机器人照做了”。 +这里的大多数失败不是复杂漏洞,而是“有人给机器人发了消息,机器人照做了”。 OpenClaw 的立场: -- **身份优先:** 决定谁可以和机器人对话(私信配对 / 允许列表 / 显式“开放”)。 -- **接着定范围:** 决定机器人允许在哪里行动(群组允许列表 + 提及门控、工具、沙箱隔离、设备权限)。 -- **最后才是模型:** 假设模型可以被操纵;设计时让操纵的影响范围受限。 +- **身份优先:** 决定谁可以与机器人交谈(私信配对 / 允许列表 / 显式“开放”)。 +- **然后限定范围:** 决定机器人可以在哪里行动(群组允许列表 + 提及门控、工具、沙箱隔离、设备权限)。 +- **最后才是模型:** 假设模型可能被操纵;设计时让操纵的影响半径受限。 ## 命令授权模型 -斜杠命令和指令只会对 **已授权发送者** 生效。授权来自 -渠道允许列表/配对以及 `commands.useAccessGroups`(参见 [配置](/zh-CN/gateway/configuration) -和 [斜杠命令](/zh-CN/tools/slash-commands))。如果渠道允许列表为空或包含 `"*"`, +斜杠命令和指令只会对 **已授权发送者** 生效。授权来源于 +渠道允许列表/配对以及 `commands.useAccessGroups`(见 [配置](/zh-CN/gateway/configuration) +和 [斜杠命令](/zh-CN/tools/slash-commands))。如果某个渠道允许列表为空或包含 `"*"`, 该渠道的命令实际上就是开放的。 -`/exec` 是面向已授权操作员的仅会话便利功能。它 **不会** 写入配置或 +`/exec` 是面向已授权操作员的仅会话便利功能。它**不会**写入配置,也不会 更改其他会话。 ## 控制平面工具风险 -两个内置工具可以进行持久性的控制平面更改: +两个内置工具可以进行持久性控制平面更改: -- `gateway` 可以通过 `config.schema.lookup` / `config.get` 检查配置,并可以通过 `config.apply`、`config.patch` 和 `update.run` 进行持久更改。 -- `cron` 可以创建计划任务,这些任务会在原始聊天/任务结束后继续运行。 +- `gateway` 可以通过 `config.schema.lookup` / `config.get` 检查配置,并可以通过 `config.apply`、`config.patch` 和 `update.run` 进行持久性更改。 +- `cron` 可以创建在原始聊天/任务结束后仍会继续运行的定时作业。 -仅限所有者的 `gateway` 运行时工具仍然拒绝重写 +仅限所有者的 `gateway` 运行时工具仍会拒绝重写 `tools.exec.ask` 或 `tools.exec.security`;旧版 `tools.bash.*` 别名会在写入前 -规范化到相同的受保护 exec 路径。 -智能体驱动的 `gateway config.apply` 和 `gateway config.patch` 编辑默认失败关闭: -只有一小组提示词、模型和提及门控路径可由智能体调节。因此,新的敏感配置树会受到保护, +规范化到同一组受保护的执行路径。 +智能体驱动的 `gateway config.apply` 和 `gateway config.patch` 编辑默认会 +失败关闭:只有一小组提示词、模型和提及门控 +路径可由智能体调节。因此,新的敏感配置树会受到保护, 除非它们被有意添加到允许列表。 对于任何处理不受信任内容的智能体/界面,默认拒绝这些工具: @@ -494,30 +496,30 @@ OpenClaw 的立场: ## 插件 -插件与 Gateway 网关 **同进程** 运行。将它们视为受信任代码: +插件与 Gateway 网关在 **同一进程内** 运行。请将它们视为可信代码: -- 只从你信任的来源安装插件。 +- 只安装来自你信任来源的插件。 - 优先使用显式 `plugins.allow` 允许列表。 - 启用前审查插件配置。 - 插件更改后重启 Gateway 网关。 - 如果你安装或更新插件(`openclaw plugins install `、`openclaw plugins update `),请像运行不受信任代码一样对待: - - 安装路径是活动插件安装根目录下的逐插件目录。 - - OpenClaw 会在安装/更新前运行内置危险代码扫描。默认情况下,`critical` 发现会阻止操作。 - - OpenClaw 使用 `npm pack`,然后在该目录中运行项目本地的 `npm install --omit=dev --ignore-scripts`。继承的全局 npm 安装设置会被忽略,因此依赖项会留在插件安装路径下。 + - 安装路径是活动插件安装根目录下的按插件目录。 + - OpenClaw 会在安装/更新前运行内置危险代码扫描。`critical` 发现默认会阻止。 + - npm 和 git 插件安装只会在显式安装/更新流程期间运行包管理器依赖收敛。本地路径和归档会被视为自包含插件包;OpenClaw 会复制/引用它们,而不会运行 `npm install`。 - 优先使用固定的精确版本(`@scope/pkg@1.2.3`),并在启用前检查磁盘上解包后的代码。 - - `--dangerously-force-unsafe-install` 只是插件安装/更新流程中用于内置扫描误报的破窗选项。它不会绕过插件 `before_install` 钩子策略阻断,也不会绕过扫描失败。 - - Gateway 网关支持的 Skills 依赖安装遵循相同的危险/可疑拆分:除非调用方显式设置 `dangerouslyForceUnsafeInstall`,否则内置 `critical` 发现会阻止操作,而可疑发现仍然只发出警告。`openclaw skills install` 仍是单独的 ClawHub Skill 下载/安装流程。 + - `--dangerously-force-unsafe-install` 只是插件安装/更新流程中针对内置扫描误报的破窗选项。它不会绕过插件 `before_install` 钩子策略阻止,也不会绕过扫描失败。 + - Gateway 网关支持的 Skills 依赖安装遵循相同的危险/可疑划分:除非调用方显式设置 `dangerouslyForceUnsafeInstall`,否则内置 `critical` 发现会阻止,而可疑发现仍只发出警告。`openclaw skills install` 仍是独立的 ClawHub skill 下载/安装流程。 详情:[插件](/zh-CN/tools/plugin) ## 私信访问模型:配对、允许列表、开放、禁用 -所有当前支持私信的渠道都支持一个私信策略(`dmPolicy` 或 `*.dm.policy`),它会在消息处理 **之前** 门控传入私信: +所有当前支持私信的渠道都支持一个私信策略(`dmPolicy` 或 `*.dm.policy`),它会在处理消息**之前**门控入站私信: -- `pairing`(默认):未知发送者会收到一个短配对码,机器人会忽略他们的消息,直到批准为止。代码 1 小时后过期;重复私信不会重新发送代码,直到创建新的请求。默认情况下,每个渠道待处理请求上限为 **3 个**。 -- `allowlist`:未知发送者会被阻止(没有配对握手)。 -- `open`:允许任何人发送私信(公开)。**要求** 渠道允许列表包含 `"*"`(显式选择加入)。 -- `disabled`:完全忽略传入私信。 +- `pairing`(默认):未知发送者会收到一个简短配对码,机器人会忽略其消息,直到批准为止。代码会在 1 小时后过期;重复私信不会重新发送代码,直到创建新请求为止。待处理请求默认限制为 **每个渠道 3 个**。 +- `allowlist`:未知发送者会被阻止(无配对握手)。 +- `open`:允许任何人私信(公开)。**要求** 渠道允许列表包含 `"*"`(显式选择加入)。 +- `disabled`:完全忽略入站私信。 通过 CLI 批准: @@ -530,7 +532,7 @@ openclaw pairing approve ## 私信会话隔离(多用户模式) -默认情况下,OpenClaw 会将 **所有私信路由到主会话**,这样你的助手可以在设备和渠道之间保持连续性。如果 **多人** 可以给机器人发私信(开放私信或多人允许列表),请考虑隔离私信会话: +默认情况下,OpenClaw 会将 **所有私信路由到主会话**,以便你的助手在设备和渠道之间保持连续性。如果 **多人** 可以私信机器人(开放私信或多人允许列表),请考虑隔离私信会话: ```json5 { @@ -538,72 +540,72 @@ openclaw pairing approve } ``` -这可以防止跨用户上下文泄漏,同时保持群聊隔离。 +这会防止跨用户上下文泄漏,同时保持群聊隔离。 -这是消息上下文边界,不是主机管理员边界。如果用户彼此对抗,并且共享同一个 Gateway 网关主机/配置,请按信任边界运行单独的网关。 +这是消息上下文边界,不是主机管理员边界。如果用户之间互不信任,并且共享同一个 Gateway 网关主机/配置,请改为按信任边界运行独立 Gateway 网关。 ### 安全私信模式(推荐) 将上面的片段视为 **安全私信模式**: -- 默认:`session.dmScope: "main"`(所有私信共享一个会话以保持连续性)。 -- 本地 CLI 新手引导默认值:未设置时写入 `session.dmScope: "per-channel-peer"`(保留现有显式值)。 +- 默认:`session.dmScope: "main"`(所有私信共享一个会话,以保持连续性)。 +- 本地 CLI 新手引导默认值:未设置时写入 `session.dmScope: "per-channel-peer"`(保留已有显式值)。 - 安全私信模式:`session.dmScope: "per-channel-peer"`(每个渠道+发送者组合获得隔离的私信上下文)。 -- 跨渠道同一发送者隔离:`session.dmScope: "per-peer"`(每个发送者在同类型的所有渠道中获得一个会话)。 +- 跨渠道对等方隔离:`session.dmScope: "per-peer"`(每个发送者在同一类型的所有渠道中获得一个会话)。 -如果你在同一渠道上运行多个账号,请改用 `per-account-channel-peer`。如果同一个人在多个渠道联系你,请使用 `session.identityLinks` 将这些私信会话合并为一个规范身份。参见 [会话管理](/zh-CN/concepts/session) 和 [配置](/zh-CN/gateway/configuration)。 +如果你在同一渠道上运行多个账号,请改用 `per-account-channel-peer`。如果同一个人通过多个渠道联系你,请使用 `session.identityLinks` 将这些私信会话折叠为一个规范身份。见 [会话管理](/zh-CN/concepts/session) 和 [配置](/zh-CN/gateway/configuration)。 ## 私信和群组的允许列表 OpenClaw 有两个独立的“谁可以触发我?”层: -- **私信允许列表**(`allowFrom` / `channels.discord.allowFrom` / `channels.slack.allowFrom`;旧版:`channels.discord.dm.allowFrom`、`channels.slack.dm.allowFrom`):谁允许在直接消息中与机器人对话。 - - 当 `dmPolicy="pairing"` 时,批准会写入 `~/.openclaw/credentials/` 下按账号范围划分的配对允许列表存储(默认账号为 `-allowFrom.json`,非默认账号为 `--allowFrom.json`),并与配置允许列表合并。 -- **群组允许列表**(特定于渠道):机器人会接受哪些群组/渠道/服务器的消息。 +- **私信允许列表**(`allowFrom` / `channels.discord.allowFrom` / `channels.slack.allowFrom`;旧版:`channels.discord.dm.allowFrom`、`channels.slack.dm.allowFrom`):谁被允许在直接消息中与机器人交谈。 + - 当 `dmPolicy="pairing"` 时,批准会写入 `~/.openclaw/credentials/` 下账号作用域的配对允许列表存储(默认账号为 `-allowFrom.json`,非默认账号为 `--allowFrom.json`),并与配置允许列表合并。 +- **群组允许列表**(特定于渠道):机器人究竟会接受哪些群组/渠道/服务器的消息。 - 常见模式: - - `channels.whatsapp.groups`、`channels.telegram.groups`、`channels.imessage.groups`:逐群组默认值,例如 `requireMention`;设置后,它也会充当群组允许列表(包含 `"*"` 以保留全部允许行为)。 + - `channels.whatsapp.groups`、`channels.telegram.groups`、`channels.imessage.groups`:按群组的默认值,例如 `requireMention`;设置后,它也会作为群组允许列表(包含 `"*"` 可保持全部允许行为)。 - `groupPolicy="allowlist"` + `groupAllowFrom`:限制谁可以在群组会话 _内部_ 触发机器人(WhatsApp/Telegram/Signal/iMessage/Microsoft Teams)。 - - `channels.discord.guilds` / `channels.slack.channels`:逐界面允许列表 + 提及默认值。 - - 群组检查按此顺序运行:先检查 `groupPolicy`/群组允许列表,再检查提及/回复激活。 - - 回复机器人消息(隐式提及)**不会** 绕过 `groupAllowFrom` 等发送者允许列表。 + - `channels.discord.guilds` / `channels.slack.channels`:按界面的允许列表 + 提及默认值。 + - 群组检查按以下顺序运行:先检查 `groupPolicy`/群组允许列表,再检查提及/回复激活。 + - 回复机器人消息(隐式提及)**不会**绕过像 `groupAllowFrom` 这样的发送者允许列表。 - **安全注意事项:** 将 `dmPolicy="open"` 和 `groupPolicy="open"` 视为最后手段设置。它们应极少使用;除非你完全信任房间中的每个成员,否则优先使用配对 + 允许列表。 详情:[配置](/zh-CN/gateway/configuration) 和 [群组](/zh-CN/channels/groups) -## 提示词注入(它是什么,为什么重要) +## 提示注入(是什么,为什么重要) -提示词注入是指攻击者精心构造消息,操纵模型做出不安全的行为(“忽略你的指令”、“转储你的文件系统”、“打开此链接并运行命令”等)。 +提示注入是指攻击者精心构造一条消息,操纵模型执行不安全的操作(“忽略你的指令”、“转储你的文件系统”、“打开这个链接并运行命令”等)。 -即使有强系统提示词,**提示词注入仍未被解决**。系统提示词护栏只是软性指导;硬性执行来自工具策略、exec 批准、沙箱隔离和渠道允许列表(并且操作员可以按设计禁用这些)。实践中有帮助的是: +即使有强系统提示词,**提示注入也没有被解决**。系统提示词护栏只是软性指导;硬性强制来自工具策略、执行批准、沙箱隔离和渠道允许列表(并且操作员按设计可以禁用这些)。实践中有帮助的是: -- 传入私信保持锁定(配对/允许名单)。 -- 在群组中优先使用提及门控;避免在公共房间中使用“始终在线”的机器人。 -- 默认将链接、附件和粘贴的指令视为有敌意。 -- 在沙箱中运行敏感工具执行;不要把密钥放在智能体可访问的文件系统中。 -- 注意:沙箱隔离是选择加入的。如果沙箱模式关闭,隐式 `host=auto` 会解析为 Gateway 网关主机。显式 `host=sandbox` 仍会安全失败,因为没有可用的沙箱运行时。如果你希望在配置中显式表达该行为,请设置 `host=gateway`。 -- 将高风险工具(`exec`、`browser`、`web_fetch`、`web_search`)限制给受信任的智能体或显式允许名单。 -- 如果你将解释器(`python`、`node`、`ruby`、`perl`、`php`、`lua`、`osascript`)加入允许名单,请启用 `tools.exec.strictInlineEval`,这样内联求值形式仍需要显式批准。 -- Shell 批准分析也会拒绝 **未加引号的 heredoc** 中的 POSIX 参数展开形式(`$VAR`、`$?`、`$$`、`$1`、`$@`、`${…}`),因此加入允许名单的 heredoc 正文无法把 shell 展开伪装成纯文本绕过允许名单审查。给 heredoc 终止符加引号(例如 `<<'EOF'`)以选择字面正文语义;会展开变量的未加引号 heredoc 会被拒绝。 -- **模型选择很重要:**较旧/较小/旧版模型对提示注入和工具误用的鲁棒性明显较弱。对于启用了工具的智能体,请使用可用的最强最新一代、经过指令加固的模型。 +- 保持入站私信受限(配对/允许列表)。 +- 在群组中优先使用提及门禁;避免在公共聊天室中使用“始终在线”的机器人。 +- 默认将链接、附件和粘贴的指令视为恶意内容。 +- 在沙箱中运行敏感工具执行;不要让密钥出现在智能体可访问的文件系统中。 +- 注意:沙箱隔离是选择启用的。如果沙箱模式关闭,隐式 `host=auto` 会解析到 Gateway 网关主机。显式 `host=sandbox` 仍会失败关闭,因为没有可用的沙箱运行时。如果你希望在配置中明确这种行为,请设置 `host=gateway`。 +- 将高风险工具(`exec`、`browser`、`web_fetch`、`web_search`)限制给受信任的智能体或显式允许列表。 +- 如果你允许列表中包含解释器(`python`、`node`、`ruby`、`perl`、`php`、`lua`、`osascript`),请启用 `tools.exec.strictInlineEval`,这样内联 eval 形式仍需要显式批准。 +- Shell 批准分析还会拒绝 **未加引号的 heredoc** 中的 POSIX 参数展开形式(`$VAR`、`$?`、`$$`、`$1`、`$@`、`${…}`),因此允许列表中的 heredoc 正文无法把 shell 展开伪装成纯文本绕过允许列表审查。给 heredoc 终止符加引号(例如 `<<'EOF'`)即可选择使用字面正文语义;会展开变量的未加引号 heredoc 会被拒绝。 +- **模型选择很重要:** 较旧、较小或旧式模型在抵御提示注入和工具误用方面明显不够稳健。对于启用工具的智能体,请使用可用的最强、最新一代、经过指令加固的模型。 -应视为不受信任的危险信号: +需要视为不可信的危险信号: -- “读取此文件/URL,并严格按其中所说执行。” +- “读取这个文件/URL,并完全按照其中内容执行。” - “忽略你的系统提示或安全规则。” -- “透露你的隐藏指令或工具输出。” +- “泄露你的隐藏指令或工具输出。” - “粘贴 `~/.openclaw` 或你的日志的完整内容。” -## 外部内容特殊 token 清理 +## 外部内容特殊令牌清理 -OpenClaw 会在封装的外部内容和元数据到达模型之前,剥离常见自托管 LLM 聊天模板的特殊 token 字面量。覆盖的标记族包括 Qwen/ChatML、Llama、Gemma、Mistral、Phi 和 GPT-OSS 角色/轮次 token。 +OpenClaw 会在封装的外部内容和元数据到达模型之前,移除常见自托管 LLM 聊天模板特殊令牌字面量。覆盖的标记族包括 Qwen/ChatML、Llama、Gemma、Mistral、Phi,以及 GPT-OSS 角色/轮次令牌。 原因: -- 面向自托管模型的 OpenAI 兼容后端有时会保留出现在用户文本中的特殊 token,而不是屏蔽它们。否则,能够写入传入外部内容(抓取的页面、电子邮件正文、文件内容工具输出)的攻击者可以注入一个合成的 `assistant` 或 `system` 角色边界,并逃逸封装内容的防护。 -- 清理发生在外部内容封装层,因此会统一应用于抓取/读取工具和传入渠道内容,而不是按提供商分别处理。 -- 出站模型响应已经有单独的清理器,会在最终渠道投递边界从用户可见回复中剥离泄露的 ``、``、``、`` 以及类似的内部运行时脚手架。外部内容清理器是对应的传入侧机制。 +- 面向自托管模型的 OpenAI 兼容后端有时会保留用户文本中出现的特殊令牌,而不是屏蔽它们。否则,能够写入入站外部内容的攻击者(抓取页面、邮件正文、文件内容工具输出)可能会注入合成的 `assistant` 或 `system` 角色边界,并逃逸封装内容的防护栏。 +- 清理发生在外部内容封装层,因此它会统一应用于抓取/读取工具和入站渠道内容,而不是按提供商分别处理。 +- 出站模型响应已经有单独的清理器,会在最终渠道投递边界,从用户可见回复中移除泄露的 ``、``、``、`` 和类似内部运行时脚手架。外部内容清理器是其入站对应机制。 -这不会取代本页中的其他加固措施——`dmPolicy`、允许名单、exec 批准、沙箱隔离和 `contextVisibility` 仍然承担主要工作。它关闭了针对自托管栈的一个特定 tokenizer 层绕过,这类栈会原样转发带特殊 token 的用户文本。 +这不能替代本页中的其他加固措施——`dmPolicy`、允许列表、exec 批准、沙箱隔离和 `contextVisibility` 仍然承担主要工作。它封堵的是一种特定的分词器层绕过:针对会原样转发含特殊令牌用户文本的自托管栈。 ## 不安全外部内容绕过标志 @@ -613,82 +615,73 @@ OpenClaw 包含显式绕过标志,可禁用外部内容安全封装: - `hooks.gmail.allowUnsafeExternalContent` - Cron 载荷字段 `allowUnsafeExternalContent` -指南: +指导: -- 在生产环境中保持这些未设置/为 false。 -- 仅在范围严格限定的调试中临时启用。 +- 在生产环境中保持这些项未设置/为 false。 +- 仅为严格限定范围的调试临时启用。 - 如果启用,请隔离该智能体(沙箱 + 最少工具 + 专用会话命名空间)。 -钩子风险说明: +Hooks 风险说明: -- 钩子负载是不可信内容,即使投递来自你控制的系统(邮件/文档/Web 内容可能携带提示注入)。 -- 较弱的模型层级会增加这种风险。对于由钩子驱动的自动化,优先使用强大的现代模型层级,并保持严格的工具策略(`tools.profile: "messaging"` 或更严格),还应尽可能使用沙箱隔离。 +- Hook 载荷是不可信内容,即使投递来自你控制的系统(邮件/文档/Web 内容也可能携带提示注入)。 +- 较弱的模型层级会增加此风险。对于 Hook 驱动的自动化,优先使用强大的现代模型层级,并保持严格的工具策略(`tools.profile: "messaging"` 或更严格),并尽可能使用沙箱隔离。 -### 提示注入不需要公开私信 +### 提示注入不需要公共私信 -即使**只有你**可以给机器人发消息,提示注入仍可能通过机器人读取的任何**不可信内容**发生(Web 搜索/抓取结果、浏览器页面、电子邮件、文档、附件、粘贴的日志/代码)。换句话说:发送者并不是唯一的威胁面;**内容本身**也可能携带对抗性指令。 +即使 **只有你** 可以给机器人发消息,提示注入仍可能通过机器人读取的任何 **不可信内容** 发生(Web 搜索/抓取结果、浏览器页面、邮件、文档、附件、粘贴的日志/代码)。换句话说:发送者不是唯一威胁面;**内容本身** 也可能携带对抗性指令。 -启用工具后,典型风险是泄露上下文或触发工具调用。通过以下方式降低影响范围: +启用工具时,典型风险是外泄上下文或触发工具调用。通过以下方式降低影响范围: -- 使用只读或禁用工具的**阅读智能体**来总结不可信内容, - 然后将摘要传递给你的主智能体。 -- 除非需要,否则为启用了工具的智能体关闭 `web_search` / `web_fetch` / `browser`。 -- 对于 OpenResponses URL 输入(`input_file` / `input_image`),设置严格的 - `gateway.http.endpoints.responses.files.urlAllowlist` 和 - `gateway.http.endpoints.responses.images.urlAllowlist`,并保持较低的 `maxUrlParts`。 - 空允许列表会被视为未设置;如果你想完全禁用 URL 抓取,请使用 `files.allowUrl: false` / `images.allowUrl: false`。 -- 对于 OpenResponses 文件输入,解码后的 `input_file` 文本仍会作为 - **不可信外部内容**注入。不要仅仅因为 Gateway 网关在本地解码了文件文本,就认为文件文本可信。注入的块仍携带明确的 - `<<>>` 边界标记以及 `Source: External` - 元数据,即使此路径省略了更长的 `SECURITY NOTICE:` 横幅。 -- 当媒体理解从附加文档中提取文本并将该文本追加到媒体提示时,也会应用同样基于标记的包装。 -- 为任何接触不可信输入的智能体启用沙箱隔离和严格的工具允许列表。 -- 不要把密钥放入提示;改为通过 Gateway 网关主机上的环境变量/配置传递它们。 +- 使用只读或禁用工具的 **阅读智能体** 来总结不可信内容,然后将摘要传给你的主智能体。 +- 对启用工具的智能体保持 `web_search` / `web_fetch` / `browser` 关闭,除非确实需要。 +- 对于 OpenResponses URL 输入(`input_file` / `input_image`),设置严格的 `gateway.http.endpoints.responses.files.urlAllowlist` 和 `gateway.http.endpoints.responses.images.urlAllowlist`,并保持 `maxUrlParts` 较低。空允许列表会被视为未设置;如果你想完全禁用 URL 抓取,请使用 `files.allowUrl: false` / `images.allowUrl: false`。 +- 对于 OpenResponses 文件输入,解码后的 `input_file` 文本仍会作为 **不可信外部内容** 注入。不要仅因为 Gateway 网关在本地解码了文件文本,就认为它是可信的。注入块仍会携带显式的 `<<>>` 边界标记以及 `Source: External` 元数据,尽管这一路径会省略更长的 `SECURITY NOTICE:` 横幅。 +- 当媒体理解在将文本追加到媒体提示之前从附加文档中提取文本时,也会应用相同的基于标记的封装。 +- 对任何接触不可信输入的智能体启用沙箱隔离和严格的工具允许列表。 +- 不要把密钥放进提示;改为通过 Gateway 网关主机上的环境变量/配置传递。 ### 自托管 LLM 后端 -兼容 OpenAI 的自托管后端,例如 vLLM、SGLang、TGI、LM Studio, -或自定义 Hugging Face 分词器栈,在处理聊天模板特殊 token 的方式上可能不同于托管提供商。如果后端将 -`<|im_start| +OpenAI 兼容的自托管后端,例如 vLLM、SGLang、TGI、LM Studio,或自定义 Hugging Face 分词器栈,在处理聊天模板特殊令牌的方式上可能不同于托管提供商。如果后端会把用户内容中的 `<|im_start|>`、`<|start_header_id|>` 或 `` 等字面字符串分词为结构性聊天模板令牌,不可信文本就可能尝试在分词器层伪造角色边界。 -OpenClaw 会先从已包装的外部内容中剥离常见模型系列的特殊 token 字面量,然后再将其分派给模型。保持外部内容包装处于启用状态,并优先使用可用的后端设置来拆分或转义用户提供内容中的特殊 token。OpenAI 和 Anthropic 等托管提供商已经会应用自己的请求侧清理。 +OpenClaw 会在把封装的外部内容分发给模型之前,移除常见模型族的特殊令牌字面量。请保持启用外部内容封装,并在可用时优先使用会拆分或转义用户提供内容中特殊令牌的后端设置。OpenAI 和 Anthropic 等托管提供商已经应用自己的请求侧清理。 -### 模型能力(安全注意事项) +### 模型强度(安全说明) -提示注入抵抗能力在不同模型层级之间**并不**一致。更小/更便宜的模型通常更容易受到工具滥用和指令劫持的影响,尤其是在对抗性提示下。 +提示注入抵抗能力在不同模型层级之间 **并不** 一致。较小/较便宜的模型通常更容易受到工具误用和指令劫持影响,尤其是在对抗性提示下。 -对于启用了工具的智能体,或会读取不受信任内容的智能体,使用较旧/较小模型时的提示注入风险通常过高。不要在弱模型层级上运行这些工作负载。 +对于启用工具的智能体或会读取不可信内容的智能体,使用较旧/较小模型时的提示注入风险通常过高。不要在较弱模型层级上运行这些工作负载。 建议: -- 对于任何可以运行工具或访问文件/网络的机器人,**使用最新一代、最佳层级的模型**。 -- 对启用了工具的智能体或不受信任的收件箱,**不要使用较旧/较弱/较小的层级**;提示注入风险过高。 -- 如果你必须使用较小模型,**缩小影响范围**(只读工具、强沙箱隔离、最小文件系统访问、严格允许列表)。 -- 运行小模型时,**为所有会话启用沙箱隔离**,并**禁用 web_search/web_fetch/browser**,除非输入受到严格控制。 -- 对于输入可信且不使用工具的纯聊天个人助手,较小模型通常没问题。 +- 对于任何能运行工具或接触文件/网络的机器人,**使用最新一代、最佳层级模型**。 +- 不要为启用工具的智能体或不可信收件箱使用较旧/较弱/较小层级;提示注入风险太高。 +- 如果必须使用较小模型,请 **降低影响范围**(只读工具、强沙箱隔离、最小文件系统访问、严格允许列表)。 +- 运行小模型时,请 **为所有会话启用沙箱隔离**,并 **禁用 web_search/web_fetch/browser**,除非输入受到严格控制。 +- 对于只有聊天、输入可信且没有工具的个人助手,较小模型通常可以。 ## 群组中的推理和详细输出 -`/reasoning`、`/verbose` 和 `/trace` 可能暴露内部推理、工具输出或插件诊断信息,而这些内容并不是面向公开渠道的。在群组设置中,应将它们视为**仅用于调试**,除非你明确需要,否则保持关闭。 +`/reasoning`、`/verbose` 和 `/trace` 可能暴露内部推理、工具输出或插件诊断信息,而这些信息并不适合公开渠道。在群组设置中,请将它们视为 **仅用于调试**,除非你明确需要,否则保持关闭。 -指南: +指导: -- 在公共房间中保持 `/reasoning`、`/verbose` 和 `/trace` 禁用。 -- 如果启用它们,只能在可信私信或严格受控的房间中启用。 -- 请记住:verbose 和 trace 输出可能包含工具参数、URL、插件诊断信息,以及模型看到的数据。 +- 在公共聊天室中保持 `/reasoning`、`/verbose` 和 `/trace` 禁用。 +- 如果启用它们,只在受信任的私信或严格受控的聊天室中启用。 +- 记住:详细输出和跟踪输出可能包含工具参数、URL、插件诊断信息,以及模型看到的数据。 ## 配置加固示例 ### 文件权限 -在网关主机上保持配置 + 状态私密: +在 Gateway 网关主机上保持配置和状态私有: -- `~/.openclaw/openclaw.json`:`600`(仅用户可读/写) +- `~/.openclaw/openclaw.json`:`600`(仅用户读/写) - `~/.openclaw`:`700`(仅用户) -`openclaw doctor` 可以发出警告,并提议收紧这些权限。 +`openclaw doctor` 可以发出警告并提示收紧这些权限。 ### 网络暴露(绑定、端口、防火墙) @@ -697,169 +690,197 @@ Gateway 网关在单个端口上复用 **WebSocket + HTTP**: - 默认值:`18789` - 配置/标志/环境变量:`gateway.port`、`--port`、`OPENCLAW_GATEWAY_PORT` -此 HTTP 表面包括控制 UI 和画布宿主: +这个 HTTP 暴露面包括 Control UI 和画布宿主: -- 控制 UI(SPA 资源)(默认基路径 `/`) +- Control UI(SPA 资源)(默认基础路径 `/`) - 画布宿主:`/__openclaw__/canvas/` 和 `/__openclaw__/a2ui/`(任意 HTML/JS;视为不可信内容) 如果你在普通浏览器中加载画布内容,请像对待任何其他不可信网页一样对待它: -- 不要将画布宿主暴露给不可信网络/用户。 -- 不要让画布内容与特权 Web 表面共享同源,除非你完全理解其影响。 +- 不要把画布宿主暴露给不可信网络/用户。 +- 除非你完全理解其影响,否则不要让画布内容与特权 Web 界面共享同源。 绑定模式控制 Gateway 网关监听的位置: - `gateway.bind: "loopback"`(默认):只有本地客户端可以连接。 -- 非 loopback 绑定(`"lan"`、`"tailnet"`、`"custom"`)会扩大攻击面。仅在使用网关认证(共享令牌/密码,或配置正确的可信代理)和真实防火墙时使用它们。 +- 非 loopback 绑定(`"lan"`、`"tailnet"`、`"custom"`)会扩大攻击面。只有在启用 Gateway 网关认证(共享令牌/密码,或正确配置的受信任代理)并使用真实防火墙时才使用它们。 -经验规则: +经验法则: - 优先使用 Tailscale Serve,而不是 LAN 绑定(Serve 会让 Gateway 网关保持在 loopback 上,由 Tailscale 处理访问)。 -- 如果必须绑定到 LAN,请将该端口的防火墙限制为严格的源 IP 允许列表;不要广泛端口转发。 -- 切勿在 `0.0.0.0` 上无认证暴露 Gateway 网关。 +- 如果必须绑定到 LAN,请用防火墙将端口限制到严格的源 IP 允许列表;不要广泛端口转发。 +- 绝不要在 `0.0.0.0` 上以未认证方式暴露 Gateway 网关。 ### 使用 UFW 发布 Docker 端口 -如果你在 VPS 上使用 Docker 运行 OpenClaw,请记住,发布的容器端口 -(`-p HOST:CONTAINER` 或 Compose `ports:`)通过 Docker 的转发 -链路由,而不仅仅通过主机 `INPUT` 规则。 +如果你在 VPS 上用 Docker 运行 OpenClaw,请记住,已发布的容器端口(`-p HOST:CONTAINER` 或 Compose `ports:`)会通过 Docker 的转发链路路由,而不只是主机 `INPUT` 规则。 -为使 Docker 流量与防火墙策略保持一致,请在 -`DOCKER-USER` 中强制执行规则(此链会在 Docker 自己的接受规则之前评估)。 -在许多现代发行版上,`iptables`/`ip6tables` 使用 `iptables-nft` 前端, -并且仍会将这些规则应用到 nftables 后端。 +为了让 Docker 流量与你的防火墙策略一致,请在 `DOCKER-USER` 中强制执行规则(该链会在 Docker 自身的接受规则之前被评估)。在许多现代发行版中,`iptables`/`ip6tables` 使用 `iptables-nft` 前端,并且仍会把这些规则应用到 nftables 后端。 最小允许列表示例(IPv4): -__OC_I18N_900008__ + +```bash +# /etc/ufw/after.rules (append as its own *filter section) +*filter +:DOCKER-USER - [0:0] +-A DOCKER-USER -m conntrack --ctstate ESTABLISHED,RELATED -j RETURN +-A DOCKER-USER -s 127.0.0.0/8 -j RETURN +-A DOCKER-USER -s 10.0.0.0/8 -j RETURN +-A DOCKER-USER -s 172.16.0.0/12 -j RETURN +-A DOCKER-USER -s 192.168.0.0/16 -j RETURN +-A DOCKER-USER -s 100.64.0.0/10 -j RETURN +-A DOCKER-USER -p tcp --dport 80 -j RETURN +-A DOCKER-USER -p tcp --dport 443 -j RETURN +-A DOCKER-USER -m conntrack --ctstate NEW -j DROP +-A DOCKER-USER -j RETURN +COMMIT +``` + IPv6 有单独的表。如果启用了 Docker IPv6,请在 `/etc/ufw/after6.rules` 中添加匹配策略。 -避免在文档片段中硬编码 `eth0` 这样的接口名称。接口名称 -会因 VPS 镜像而异(`ens3`、`enp*` 等),不匹配可能会意外地 -跳过你的拒绝规则。 +避免在文档片段中硬编码 `eth0` 之类的接口名。不同 VPS 镜像的接口名会有所不同(`ens3`、`enp*` 等),不匹配可能会意外跳过你的拒绝规则。 重新加载后的快速验证: -__OC_I18N_900009__ -预期的外部端口应该只包含你有意暴露的端口(对于大多数 -设置:SSH + 你的反向代理端口)。 + +```bash +ufw reload +iptables -S DOCKER-USER +ip6tables -S DOCKER-USER +nmap -sT -p 1-65535 --open +``` + +预期外部端口应仅包含你有意暴露的端口(对于大多数设置:SSH + 你的反向代理端口)。 ### mDNS/Bonjour 设备发现 -Gateway 网关通过 mDNS(端口 5353 上的 `_openclaw-gw._tcp`)广播自身存在,用于本地设备发现。在完整模式下,这包括可能暴露操作细节的 TXT 记录: +Gateway 网关通过 mDNS(端口 5353 上的 `_openclaw-gw._tcp`)广播自身存在,用于本地设备发现。在完整模式下,这包括可能暴露运行细节的 TXT 记录: - `cliPath`:CLI 二进制文件的完整文件系统路径(会暴露用户名和安装位置) -- `sshPort`:通告主机上的 SSH 可用性 +- `sshPort`:公布主机上的 SSH 可用性 - `displayName`、`lanHost`:主机名信息 -**操作安全考量:** 广播基础设施详情会让本地网络上的任何人更容易侦察。即使是文件系统路径和 SSH 可用性这类“无害”信息,也会帮助攻击者绘制你的环境地图。 +**运维安全考量:**广播基础设施细节会让本地网络上的任何人更容易侦察。即便是文件系统路径和 SSH 可用性这类“无害”信息,也会帮助攻击者绘制你的环境图谱。 **建议:** -1. **最小模式**(默认,建议用于暴露的 Gateway 网关):从 mDNS 广播中省略敏感字段: -__OC_I18N_900010__ -2. 如果你不需要本地设备发现,**完全禁用**: -__OC_I18N_900011__ -3. **完整模式**(选择启用):在 TXT 记录中包含 `cliPath` + `sshPort`: -__OC_I18N_900012__ -4. **环境变量**(替代方式):设置 `OPENCLAW_DISABLE_BONJOUR=1`,无需更改配置即可禁用 mDNS。 +1. **最小模式**(默认,推荐用于暴露的 Gateway 网关):从 mDNS 广播中省略敏感字段: -在最小模式下,Gateway 网关仍会广播足够用于设备发现的信息(`role`、`gatewayPort`、`transport`),但会省略 `cliPath` 和 `sshPort`。需要 CLI 路径信息的应用可以改为通过已认证的 WebSocket 连接获取它。 + ```json5 + { + discovery: { + mdns: { mode: "minimal" }, + }, + } + ``` + +2. 如果你不需要本地设备发现,**完全禁用**: + + ```json5 + { + discovery: { + mdns: { mode: "off" }, + }, + } + ``` + +3. **完整模式**(选择启用):在 TXT 记录中包含 `cliPath` + `sshPort`: + + ```json5 + { + discovery: { + mdns: { mode: "full" }, + }, + } + ``` + +4. **环境变量**(替代方式):设置 `OPENCLAW_DISABLE_BONJOUR=1`,无需修改配置即可禁用 mDNS。 + +在最小模式下,Gateway 网关仍会广播足够用于设备发现的信息(`role`、`gatewayPort`、`transport`),但会省略 `cliPath` 和 `sshPort`。需要 CLI 路径信息的应用可以改为通过已认证的 WebSocket 连接获取。 ### 锁定 Gateway 网关 WebSocket(本地认证) -Gateway 网关认证**默认必需**。如果未配置有效的网关认证路径, -Gateway 网关会拒绝 WebSocket 连接(失败关闭)。 +Gateway 网关认证**默认必需**。如果未配置有效的 Gateway 网关认证路径,Gateway 网关会拒绝 WebSocket 连接(失败即关闭)。 -新手引导默认会生成令牌(即使是 loopback),因此 -本地客户端必须认证。 +新手引导默认会生成一个令牌(即使是 loopback),因此本地客户端必须认证。 设置令牌,让**所有** WS 客户端都必须认证: -__OC_I18N_900013__ + +```json5 +{ + gateway: { + auth: { mode: "token", token: "your-token" }, + }, +} +``` + Doctor 可以为你生成一个:`openclaw doctor --generate-gateway-token`。 -`gateway.remote.token` 和 `gateway.remote.password` 是客户端凭证来源。它们本身**不会**保护本地 WS 访问。本地调用路径只有在 `gateway.auth.*` 未设置时,才可以使用 `gateway.remote.*` 作为后备。如果 `gateway.auth.token` 或 `gateway.auth.password` 通过 SecretRef 显式配置且未解析,解析会失败关闭(不会用远程后备掩盖)。 +`gateway.remote.token` 和 `gateway.remote.password` 是客户端凭证来源。它们本身**不会**保护本地 WS 访问。只有在未设置 `gateway.auth.*` 时,本地调用路径才可以使用 `gateway.remote.*` 作为回退。如果通过 SecretRef 显式配置了 `gateway.auth.token` 或 `gateway.auth.password` 但无法解析,解析会失败即关闭(不会用远程回退掩盖)。 -可选:使用 `wss://` 时,通过 `gateway.remote.tlsFingerprint` 固定远程 TLS。 -默认情况下,明文 `ws://` 仅限 loopback。对于可信的私有网络 -路径,请在客户端进程上设置 `OPENCLAW_ALLOW_INSECURE_PRIVATE_WS=1` -作为应急措施。这有意只作为进程环境存在,而不是 -`openclaw.json` 配置键。 -移动配对以及 Android 手动或扫码的网关路由更严格: -loopback 可接受明文,但私有 LAN、链路本地、`.local` 和 -无点主机名必须使用 TLS,除非你显式选择启用可信 -私有网络明文路径。 +可选:使用 `wss://` 时,可通过 `gateway.remote.tlsFingerprint` 固定远程 TLS。 +明文 `ws://` 默认仅限 loopback。对于受信任的私有网络路径,可在客户端进程上设置 `OPENCLAW_ALLOW_INSECURE_PRIVATE_WS=1` 作为应急破例。这是有意仅支持进程环境,而不是 `openclaw.json` 配置键。 +移动端配对以及 Android 手动或扫码的 Gateway 网关路由更严格: +loopback 接受明文,但私有 LAN、link-local、`.local` 和无点主机名必须使用 TLS,除非你显式选择启用受信任私有网络明文路径。 本地设备配对: -- 对 direct local loopback 连接,设备配对会自动批准,以保持同主机客户端顺畅。 -- OpenClaw 还有一条很窄的后端/容器本地自连接路径,用于可信共享密钥辅助流程。 -- Tailnet 和 LAN 连接,包括同主机 tailnet 绑定,都按远程配对处理,并且仍需要批准。 -- loopback 请求上的转发标头证据会取消 loopback 本地性资格。元数据升级自动批准的范围很窄。两条规则都见 [Gateway 网关配对](/gateway/pairing)。 +- 直接 local loopback 连接会自动批准设备配对,以保持同一主机客户端顺畅。 +- OpenClaw 也为受信任的共享密钥辅助流程提供一条狭窄的后端/容器本地自连接路径。 +- Tailnet 和 LAN 连接,包括同一主机的 tailnet 绑定,在配对时会被视为远程,仍需批准。 +- loopback 请求上的转发标头证据会取消其 loopback 本地性资格。元数据升级自动批准的范围很窄。两条规则请参阅 [Gateway 网关配对](/zh-CN/gateway/pairing)。 认证模式: -- `gateway.auth.mode: "token"`:共享 bearer 令牌(建议用于大多数设置)。 -- `gateway.auth.mode: "password"`:密码认证(优先通过环境变量设置:`OPENCLAW_GATEWAY_PASSWORD`)。 -- `gateway.auth.mode: "trusted-proxy"`:信任具备身份感知能力的反向代理来认证用户,并通过标头传递身份(见 [可信代理认证](/gateway/trusted-proxy-auth))。 +- `gateway.auth.mode: "token"`:共享 bearer 令牌(推荐用于大多数设置)。 +- `gateway.auth.mode: "password"`:密码认证(建议通过环境变量设置:`OPENCLAW_GATEWAY_PASSWORD`)。 +- `gateway.auth.mode: "trusted-proxy"`:信任具备身份感知能力的反向代理来认证用户,并通过标头传递身份(参见 [受信任代理认证](/zh-CN/gateway/trusted-proxy-auth))。 轮换清单(令牌/密码): -1. 生成/设置新密钥(`gateway.auth.token` 或 `OPENCLAW_GATEWAY_PASSWORD`)。 -2. 重启 Gateway 网关(如果由 macOS 应用托管 Gateway 网关,则重启该应用)。 +1. 生成/设置新的密钥(`gateway.auth.token` 或 `OPENCLAW_GATEWAY_PASSWORD`)。 +2. 重启 Gateway 网关(如果由 macOS 应用监管 Gateway 网关,则重启 macOS 应用)。 3. 更新所有远程客户端(调用 Gateway 网关的机器上的 `gateway.remote.token` / `.password`)。 -4. 验证旧凭证已无法连接。 +4. 验证旧凭证已无法再连接。 ### Tailscale Serve 身份标头 -当 `gateway.auth.allowTailscale` 为 `true`(Serve 的默认值)时,OpenClaw -会接受 Tailscale Serve 身份标头(`tailscale-user-login`),用于 Control -UI/WebSocket 认证。OpenClaw 会通过本地 Tailscale 守护进程(`tailscale whois`) -解析 `x-forwarded-for` 地址,并将其与标头匹配,从而验证身份。这只会在请求命中 loopback -且包含由 Tailscale 注入的 `x-forwarded-for`、`x-forwarded-proto` 和 `x-forwarded-host` -时触发。 -对于这条异步身份检查路径,同一 `{scope, ip}` 的失败尝试会在限流器记录失败之前被串行化。因此,来自同一个 Serve 客户端的并发错误重试可能会立即锁定第二次尝试,而不是作为两次普通不匹配并发通过。 -HTTP API 端点(例如 `/v1/*`、`/tools/invoke` 和 `/api/channels/*`) -**不会**使用 Tailscale 身份标头认证。它们仍遵循网关配置的 -HTTP 认证模式。 +当 `gateway.auth.allowTailscale` 为 `true`(Serve 的默认值)时,OpenClaw 会接受 Tailscale Serve 身份标头(`tailscale-user-login`)用于控制 UI/WebSocket 认证。OpenClaw 会通过本地 Tailscale 守护进程(`tailscale whois`)解析 `x-forwarded-for` 地址,并将其与标头匹配来验证身份。此逻辑只会在请求命中 loopback,且包含由 Tailscale 注入的 `x-forwarded-for`、`x-forwarded-proto` 和 `x-forwarded-host` 时触发。 +对于这条异步身份检查路径,在限流器记录失败之前,同一 `{scope, ip}` 的失败尝试会被串行化。因此,来自同一个 Serve 客户端的并发错误重试可能会立即锁定第二次尝试,而不是像两个普通不匹配一样竞争通过。 +HTTP API 端点(例如 `/v1/*`、`/tools/invoke` 和 `/api/channels/*`)**不**使用 Tailscale 身份标头认证。它们仍会遵循 Gateway 网关配置的 HTTP 认证模式。 重要边界说明: - Gateway 网关 HTTP bearer 认证实际上是全有或全无的操作员访问权限。 -- 将能够调用 `/v1/chat/completions`、`/v1/responses` 或 `/api/channels/*` 的凭证视为该网关的完全访问操作员密钥。 -- 在 OpenAI 兼容的 HTTP 表面上,共享密钥 bearer 认证会恢复完整默认操作员作用域(`operator.admin`、`operator.approvals`、`operator.pairing`、`operator.read`、`operator.talk.secrets`、`operator.write`)以及智能体轮次的 owner 语义;更窄的 `x-openclaw-scopes` 值不会削弱该共享密钥路径。 -- HTTP 上的逐请求作用域语义仅在请求来自带身份的模式时适用,例如可信代理认证,或私有入口上的 `gateway.auth.mode="none"`。 -- 在这些带身份的模式中,省略 `x-openclaw-scopes` 会回退到正常的操作员默认作用域集合;如果需要更窄的作用域集合,请显式发送该标头。 -- `/tools/invoke` 遵循相同的共享密钥规则:令牌/密码 bearer 认证在那里也被视为完整操作员访问权限,而带身份的模式仍会遵守声明的作用域。 -- 不要与不可信调用方共享这些凭证;建议按信任边界使用独立 Gateway 网关。 +- 将可调用 `/v1/chat/completions`、`/v1/responses` 或 `/api/channels/*` 的凭证视为该 Gateway 网关的完全访问操作员密钥。 +- 在 OpenAI 兼容 HTTP 表面上,共享密钥 bearer 认证会恢复完整的默认操作员作用域(`operator.admin`、`operator.approvals`、`operator.pairing`、`operator.read`、`operator.talk.secrets`、`operator.write`)以及智能体回合的所有者语义;更窄的 `x-openclaw-scopes` 值不会缩减该共享密钥路径。 +- HTTP 上的逐请求作用域语义仅在请求来自带身份的模式时适用,例如受信任代理认证,或私有入口上的 `gateway.auth.mode="none"`。 +- 在这些带身份的模式中,省略 `x-openclaw-scopes` 会回退到普通操作员默认作用域集合;当你需要更窄的作用域集合时,请显式发送该标头。 +- `/tools/invoke` 遵循相同的共享密钥规则:令牌/密码 bearer 认证在那里也会被视为完整操作员访问权限,而带身份的模式仍会遵循声明的作用域。 +- 不要与不受信任的调用方共享这些凭证;建议为每个信任边界使用单独的 Gateway 网关。 -**信任假设:** 无令牌 Serve 认证假设网关主机是可信的。 -不要把它当作防护恶意同主机进程的措施。如果不可信的 -本地代码可能在网关主机上运行,请禁用 `gateway.auth.allowTailscale` -并要求使用 `gateway.auth.mode: "token"` 或 `"password"` 的显式共享密钥认证。 +**信任假设:**无令牌 Serve 认证假设 Gateway 网关主机是受信任的。 +不要把它视为对恶意同主机进程的防护。如果不受信任的本地代码可能在 Gateway 网关主机上运行,请禁用 `gateway.auth.allowTailscale`,并使用 `gateway.auth.mode: "token"` 或 `"password"` 要求显式共享密钥认证。 -**安全规则:** 不要从你自己的反向代理转发这些标头。如果 -你在网关前终止 TLS 或做代理,请禁用 -`gateway.auth.allowTailscale`,并改用共享密钥认证(`gateway.auth.mode: -"token"` 或 `"password"`)或 [可信代理认证](/gateway/trusted-proxy-auth)。 +**安全规则:**不要从你自己的反向代理转发这些标头。如果你在 Gateway 网关前终止 TLS 或做代理,请禁用 `gateway.auth.allowTailscale`,改用共享密钥认证(`gateway.auth.mode: "token"` 或 `"password"`)或 [受信任代理认证](/zh-CN/gateway/trusted-proxy-auth)。 -可信代理: +受信任代理: - 如果你在 Gateway 网关前终止 TLS,请将 `gateway.trustedProxies` 设置为你的代理 IP。 -- OpenClaw 会信任来自这些 IP 的 `x-forwarded-for`(或 `x-real-ip`),用于确定客户端 IP,以执行本地配对检查和 HTTP 认证/本地检查。 +- OpenClaw 会信任来自这些 IP 的 `x-forwarded-for`(或 `x-real-ip`),以确定用于本地配对检查和 HTTP 认证/本地检查的客户端 IP。 - 确保你的代理**覆盖** `x-forwarded-for`,并阻止直接访问 Gateway 网关端口。 -见 [Tailscale](/gateway/tailscale) 和 [Web 概览](/web)。 +参见 [Tailscale](/zh-CN/gateway/tailscale) 和 [Web 概览](/zh-CN/web)。 -### 通过节点主机进行浏览器控制(推荐) +### 通过节点主机控制浏览器(推荐) -如果你的 Gateway 网关是远程的,但浏览器在另一台机器上运行,请在浏览器机器上运行一个**节点主机**, -并让 Gateway 网关代理浏览器操作(见 [浏览器工具](/tools/browser))。 -把节点配对视为管理员访问权限。 +如果你的 Gateway 网关在远程,但浏览器运行在另一台机器上,请在浏览器机器上运行**节点主机**,并让 Gateway 网关代理浏览器操作(参见 [浏览器工具](/zh-CN/tools/browser))。 +将节点配对视为管理员访问权限。 推荐模式: -- 将 Gateway 网关和节点主机保持在同一个 tailnet(Tailscale)中。 -- 有意配对节点;如果不需要浏览器代理路由,请禁用它。 +- 将 Gateway 网关和节点主机保留在同一个 tailnet(Tailscale)中。 +- 有意地配对节点;如果不需要浏览器代理路由,请禁用它。 避免: @@ -871,31 +892,31 @@ HTTP 认证模式。 假设 `~/.openclaw/`(或 `$OPENCLAW_STATE_DIR/`)下的任何内容都可能包含密钥或私有数据: - `openclaw.json`:配置可能包含令牌(Gateway 网关、远程 Gateway 网关)、提供商设置和允许列表。 -- `credentials/**`:渠道凭证(例如 WhatsApp 凭证)、配对允许列表、旧版 OAuth 导入。 -- `agents//agent/auth-profiles.json`:API 密钥、令牌配置文件、OAuth 令牌,以及可选的 `keyRef`/`tokenRef`。 -- `agents//agent/codex-home/**`:每智能体 Codex 应用服务器账号、配置、Skills、插件、原生线程状态和诊断信息。 -- `secrets.json`(可选):由 `file` SecretRef 提供商(`secrets.providers`)使用的文件后端密钥载荷。 +- `credentials/**`:渠道凭证(示例:WhatsApp 凭证)、配对允许列表、旧版 OAuth 导入。 +- `agents//agent/auth-profiles.json`:API key、令牌配置文件、OAuth 令牌,以及可选的 `keyRef`/`tokenRef`。 +- `agents//agent/codex-home/**`:每个智能体的 Codex app-server 账号、配置、Skills、插件、原生线程状态和诊断信息。 +- `secrets.json`(可选):由 `file` SecretRef provider(`secrets.providers`)使用的文件后端密钥载荷。 - `agents//agent/auth.json`:旧版兼容文件。发现静态 `api_key` 条目时会清理。 - `agents//sessions/**`:会话转录(`*.jsonl`)+ 路由元数据(`sessions.json`),可能包含私密消息和工具输出。 -- 内置插件包:已安装插件(以及它们的 `node_modules/`)。 -- `sandboxes/**`:工具沙箱工作区;可能会累积你在沙箱内读取/写入的文件副本。 +- 内置插件包:已安装的插件(以及它们的 `node_modules/`)。 +- `sandboxes/**`:工具沙箱工作区;可能会积累你在沙箱中读写文件的副本。 -加固提示: +加固建议: -- 保持权限严格(目录 `700`,文件 `600`)。 -- 在网关主机上使用全盘加密。 +- 严格设置权限(目录 `700`,文件 `600`)。 +- 在 Gateway 网关主机上使用全盘加密。 - 如果主机是共享的,建议为 Gateway 网关使用专用 OS 用户账号。 ### 工作区 `.env` 文件 -OpenClaw 会为智能体和工具加载工作区本地 `.env` 文件,但绝不允许这些文件静默覆盖网关运行时控制项。 +OpenClaw 会为智能体和工具加载工作区本地 `.env` 文件,但绝不会让这些文件静默覆盖 Gateway 网关运行时控制。 -- 任何以 `OPENCLAW_*` 开头的键都会被不可信工作区 `.env` 文件阻止。 -- Matrix、Mattermost、IRC 和 Synology Chat 的渠道端点设置也会被阻止从工作区 `.env` 覆盖,因此克隆的工作区无法通过本地端点配置重定向内置连接器流量。端点环境键(例如 `MATRIX_HOMESERVER`、`MATTERMOST_URL`、`IRC_HOST`、`SYNOLOGY_CHAT_INCOMING_URL`)必须来自网关进程环境或 `env.shellEnv`,不能来自工作区加载的 `.env`。 -- 该阻止机制是失败关闭的:未来版本中新增的运行时控制变量不能从已检入或攻击者提供的 `.env` 继承;该键会被忽略,网关保留自己的值。 -- 可信进程/OS 环境变量(网关自身的 shell、launchd/systemd 单元、应用包)仍然适用——这只约束 `.env` 文件加载。 +- 任何以 `OPENCLAW_*` 开头的键都会从不受信任的工作区 `.env` 文件中被阻止。 +- Matrix、Mattermost、IRC 和 Synology Chat 的渠道端点设置也会被阻止通过工作区 `.env` 覆盖,因此克隆的工作区无法通过本地端点配置重定向内置连接器流量。端点环境变量键(例如 `MATRIX_HOMESERVER`、`MATTERMOST_URL`、`IRC_HOST`、`SYNOLOGY_CHAT_INCOMING_URL`)必须来自 Gateway 网关进程环境或 `env.shellEnv`,不能来自工作区加载的 `.env`。 +- 阻止策略是失败即关闭:未来版本中新增的运行时控制变量不能从已检入或攻击者提供的 `.env` 继承;该键会被忽略,Gateway 网关会保留自己的值。 +- 受信任的进程/OS 环境变量(Gateway 网关自己的 shell、launchd/systemd 单元、应用包)仍然适用 — 这只限制 `.env` 文件加载。 -原因:工作区 `.env` 文件经常位于智能体代码旁边,可能被意外提交,或被工具写入。阻止整个 `OPENCLAW_*` 前缀意味着以后新增的 `OPENCLAW_*` 标志永远不会退化为从工作区状态静默继承。 +原因:工作区 `.env` 文件经常与智能体代码放在一起,可能被意外提交,或被工具写入。阻止整个 `OPENCLAW_*` 前缀意味着以后添加新的 `OPENCLAW_*` 标志时,绝不会退化为从工作区状态静默继承。 ### 日志和转录(脱敏与保留) @@ -908,183 +929,333 @@ OpenClaw 会为智能体和工具加载工作区本地 `.env` 文件,但绝不 - 保持日志和转录脱敏开启(`logging.redactSensitive: "tools"`;默认)。 - 通过 `logging.redactPatterns` 为你的环境添加自定义模式(令牌、主机名、内部 URL)。 -- 共享诊断信息时,优先使用 `openclaw status --all`(可粘贴,密钥已脱敏),而不是原始日志。 +- 共享诊断信息时,建议使用 `openclaw status --all`(可粘贴,密钥已脱敏),而不是原始日志。 - 如果不需要长期保留,请清理旧会话转录和日志文件。 -详情:[日志](/gateway/logging) +详情:[日志记录](/zh-CN/gateway/logging) ### 私信:默认配对 -__OC_I18N_900014__ -### 群组:所有位置都要求提及 -__OC_I18N_900015__ -在群聊中,仅在被明确提及时响应。 -### 独立号码(WhatsApp、Signal、Telegram) +```json5 +{ + channels: { whatsapp: { dmPolicy: "pairing" } }, +} +``` -对于基于电话号码的渠道,建议让你的 AI 使用一个不同于个人号码的单独电话号码: +### 群组:所有地方都要求提及 + +```json +{ + "channels": { + "whatsapp": { + "groups": { + "*": { "requireMention": true } + } + } + }, + "agents": { + "list": [ + { + "id": "main", + "groupChat": { "mentionPatterns": ["@openclaw", "@mybot"] } + } + ] + } +} +``` + +在群聊中,只在被明确提及时才回复。 + +### 单独的号码(WhatsApp、Signal、Telegram) + +对于基于电话号码的渠道,请考虑让你的 AI 使用与个人号码不同的单独电话号码: - 个人号码:你的对话保持私密 -- 机器人号码:AI 处理这些对话,并保持适当边界 +- 机器人号码:AI 处理这些对话,并设置适当边界 ### 只读模式(通过沙箱和工具) -你可以结合以下配置构建只读配置文件: +你可以通过组合以下内容构建只读配置: -- `agents.defaults.sandbox.workspaceAccess: "ro"`(或用 `"none"` 表示无工作区访问权限) -- 阻止 `write`、`edit`、`apply_patch`、`exec`、`process` 等的工具允许/拒绝列表。 +- `agents.defaults.sandbox.workspaceAccess: "ro"`(或使用 `"none"` 表示无工作区访问权限) +- 阻止 `write`、`edit`、`apply_patch`、`exec`、`process` 等的工具允许/拒绝列表 其他加固选项: -- `tools.exec.applyPatch.workspaceOnly: true`(默认):即使沙箱隔离关闭,也确保 `apply_patch` 无法在工作区目录之外写入/删除。仅当你明确希望 `apply_patch` 触碰工作区之外的文件时,才设置为 `false`。 -- `tools.fs.workspaceOnly: true`(可选):将 `read`/`write`/`edit`/`apply_patch` 路径以及原生提示图片自动加载路径限制到工作区目录(如果你目前允许绝对路径,并希望有一个统一护栏,这会很有用)。 -- 保持文件系统根目录范围收窄:避免将你的 home 目录这类宽泛根目录用于智能体工作区/沙箱工作区。宽泛根目录可能会把敏感本地文件(例如 `~/.openclaw` 下的状态/配置)暴露给文件系统工具。 +- `tools.exec.applyPatch.workspaceOnly: true`(默认):确保即使沙箱隔离关闭,`apply_patch` 也无法在工作区目录外写入/删除。只有在你有意让 `apply_patch` 触碰工作区外的文件时,才将其设为 `false`。 +- `tools.fs.workspaceOnly: true`(可选):将 `read`/`write`/`edit`/`apply_patch` 路径和原生提示词图片自动加载路径限制在工作区目录内(如果你目前允许绝对路径,并想要一个统一防护栏,这会很有用)。 +- 保持文件系统根目录范围狭窄:避免将你的主目录等宽泛根目录用于智能体工作区/沙箱工作区。宽泛根目录可能会把敏感本地文件(例如 `~/.openclaw` 下的状态/配置)暴露给文件系统工具。 ### 安全基线(复制/粘贴) -一个“安全默认”配置示例:保持 Gateway 网关私有,要求私信配对,并避免常驻群聊机器人: -__OC_I18N_900016__ -如果你还希望工具执行“默认更安全”,请为任何非所有者智能体添加沙箱 + 拒绝危险工具(示例见下文“按智能体访问配置文件”)。 +一个“安全默认”配置会让 Gateway 网关保持私有、要求私信配对,并避免常驻群机器人: -聊天驱动的智能体轮次的内置基线:非所有者发送者不能使用 `cron` 或 `gateway` 工具。 +```json5 +{ + gateway: { + mode: "local", + bind: "loopback", + port: 18789, + auth: { mode: "token", token: "your-long-random-token" }, + }, + channels: { + whatsapp: { + dmPolicy: "pairing", + groups: { "*": { requireMention: true } }, + }, + }, +} +``` + +如果你还想让工具执行“默认更安全”,请为任何非所有者智能体添加沙箱并拒绝危险工具(示例见下文“按智能体访问配置文件”)。 + +聊天驱动的智能体轮次内置基线:非所有者发送者无法使用 `cron` 或 `gateway` 工具。 ## 沙箱隔离(推荐) -专门文档:[沙箱隔离](/gateway/sandboxing) +专门文档:[沙箱隔离](/zh-CN/gateway/sandboxing) -两种互补方式: +两种互补方法: -- **在 Docker 中运行完整 Gateway 网关**(容器边界):[Docker](/install/docker) -- **工具沙箱**(`agents.defaults.sandbox`,主机 Gateway 网关 + 沙箱隔离工具;Docker 是默认后端):[沙箱隔离](/gateway/sandboxing) +- **在 Docker 中运行完整 Gateway 网关**(容器边界):[Docker](/zh-CN/install/docker) +- **工具沙箱**(`agents.defaults.sandbox`,主机 Gateway 网关 + 沙箱隔离工具;Docker 是默认后端):[沙箱隔离](/zh-CN/gateway/sandboxing) -为防止跨智能体访问,请将 `agents.defaults.sandbox.scope` 保持为 `"agent"`(默认),或使用 `"session"` 以获得更严格的按会话隔离。`scope: "shared"` 使用单个容器或工作区。 +为防止跨智能体访问,请将 `agents.defaults.sandbox.scope` 保持为 `"agent"`(默认),或使用 `"session"` 以获得更严格的按会话隔离。`scope: "shared"` 会使用单个容器或工作区。 还应考虑沙箱内的智能体工作区访问权限: -- `agents.defaults.sandbox.workspaceAccess: "none"`(默认)会让智能体工作区不可访问;工具针对 `~/.openclaw/sandboxes` 下的沙箱工作区运行 -- `agents.defaults.sandbox.workspaceAccess: "ro"` 会将智能体工作区以只读方式挂载到 `/agent`(禁用 `write`/`edit`/`apply_patch`) -- `agents.defaults.sandbox.workspaceAccess: "rw"` 会将智能体工作区以读写方式挂载到 `/workspace` -- 额外的 `sandbox.docker.binds` 会根据规范化和标准化后的源路径进行验证。父级符号链接技巧和标准 home 别名如果解析到 `/etc`、`/var/run` 或 OS home 下的凭据目录等被阻止的根目录,仍会失败关闭。 +- `agents.defaults.sandbox.workspaceAccess: "none"`(默认)让智能体工作区不可访问;工具会针对 `~/.openclaw/sandboxes` 下的沙箱工作区运行 +- `agents.defaults.sandbox.workspaceAccess: "ro"` 将智能体工作区以只读方式挂载到 `/agent`(禁用 `write`/`edit`/`apply_patch`) +- `agents.defaults.sandbox.workspaceAccess: "rw"` 将智能体工作区以读写方式挂载到 `/workspace` +- 额外的 `sandbox.docker.binds` 会基于已规范化和规范路径化的源路径进行验证。父级符号链接技巧和规范主目录别名如果解析到被阻止的根目录(例如 `/etc`、`/var/run` 或 OS 主目录下的凭证目录),仍会默认拒绝。 -`tools.elevated` 是在沙箱外运行 exec 的全局基线逃生口。有效主机默认是 `gateway`,当 exec 目标配置为 `node` 时则为 `node`。保持 `tools.elevated.allowFrom` 严格,不要为陌生人启用它。你还可以通过 `agents.list[].tools.elevated` 按智能体进一步限制提权。参见[提权模式](/tools/elevated)。 +`tools.elevated` 是在沙箱外运行 exec 的全局基线逃逸开关。有效主机默认为 `gateway`,或在 exec 目标配置为 `node` 时为 `node`。请严格限制 `tools.elevated.allowFrom`,不要为陌生人启用它。你还可以通过 `agents.list[].tools.elevated` 进一步按智能体限制提升权限。参见[提权模式](/zh-CN/tools/elevated)。 -### 子智能体委派护栏 +### 子智能体委派防护栏 -如果你允许会话工具,请将委派的子智能体运行视为另一个边界决策: +如果你允许会话工具,请把委派的子智能体运行视为另一个边界决策: -- 除非智能体确实需要委派,否则拒绝 `sessions_spawn`。 +- 拒绝 `sessions_spawn`,除非智能体确实需要委派。 - 将 `agents.defaults.subagents.allowAgents` 以及任何按智能体的 `agents.list[].subagents.allowAgents` 覆盖限制为已知安全的目标智能体。 -- 对于任何必须保持沙箱隔离的工作流,请用 `sandbox: "require"` 调用 `sessions_spawn`(默认是 `inherit`)。 +- 对于任何必须保持沙箱隔离的工作流,调用 `sessions_spawn` 时使用 `sandbox: "require"`(默认是 `inherit`)。 - 当目标子运行时未被沙箱隔离时,`sandbox: "require"` 会快速失败。 ## 浏览器控制风险 -启用浏览器控制会让模型具备驱动真实浏览器的能力。 -如果该浏览器配置文件已经包含已登录会话,模型就能访问这些账户和数据。请将浏览器配置文件视为**敏感状态**: +启用浏览器控制会赋予模型驱动真实浏览器的能力。 +如果该浏览器配置文件已经包含已登录会话,模型就能 +访问这些账号和数据。请将浏览器配置文件视为**敏感状态**: - 优先为智能体使用专用配置文件(默认的 `openclaw` 配置文件)。 -- 避免将智能体指向你个人日常使用的配置文件。 -- 除非你信任沙箱隔离智能体,否则保持主机浏览器控制关闭。 -- 独立的 loopback 浏览器控制 API 只遵循共享密钥认证(Gateway 网关令牌 bearer 认证或 Gateway 网关密码)。它不使用受信代理或 Tailscale Serve 身份标头。 -- 将浏览器下载内容视为不可信输入;优先使用隔离的下载目录。 -- 如有可能,在智能体配置文件中禁用浏览器同步/密码管理器(降低影响范围)。 -- 对于远程 Gateway 网关,假设“浏览器控制”等同于对该配置文件能访问的任何内容拥有“操作员访问权限”。 -- 保持 Gateway 网关和 node 主机仅限 tailnet;避免将浏览器控制端口暴露给 LAN 或公网 Internet。 -- 不需要浏览器代理路由时将其禁用(`gateway.nodes.browser.mode="off"`)。 -- Chrome MCP 现有会话模式**并不**“更安全”;它可以以你的身份访问该主机 Chrome 配置文件能触达的任何内容。 +- 避免将智能体指向你的个人日常使用配置文件。 +- 除非你信任沙箱隔离智能体,否则保持主机浏览器控制禁用。 +- 独立的 local loopback 浏览器控制 API 只遵循共享密钥认证 + (Gateway 网关令牌 bearer 认证或 Gateway 网关密码)。它不会使用 + trusted-proxy 或 Tailscale Serve 身份标头。 +- 将浏览器下载内容视为不受信任的输入;优先使用隔离的下载目录。 +- 如果可行,在智能体配置文件中禁用浏览器同步/密码管理器(降低影响范围)。 +- 对于远程 Gateway 网关,假定“浏览器控制”等同于“操作者访问”,可访问该配置文件能触达的任何内容。 +- 让 Gateway 网关和 node 主机仅限 tailnet;避免将浏览器控制端口暴露给 LAN 或公网。 +- 不需要时禁用浏览器代理路由(`gateway.nodes.browser.mode="off"`)。 +- Chrome MCP 现有会话模式**并不**“更安全”;它可以以你的身份操作该主机 Chrome 配置文件能触达的任何内容。 ### 浏览器 SSRF 策略(默认严格) -OpenClaw 的浏览器导航策略默认严格:私有/内部目标会保持阻止,除非你明确选择启用。 +OpenClaw 的浏览器导航策略默认严格:除非你显式选择加入,否则私有/内部目标会保持阻止。 - 默认:`browser.ssrfPolicy.dangerouslyAllowPrivateNetwork` 未设置,因此浏览器导航会继续阻止私有/内部/特殊用途目标。 -- 旧版别名:为兼容性仍接受 `browser.ssrfPolicy.allowPrivateNetwork`。 -- 选择启用模式:设置 `browser.ssrfPolicy.dangerouslyAllowPrivateNetwork: true` 以允许私有/内部/特殊用途目标。 -- 在严格模式下,使用 `hostnameAllowlist`(类似 `*.example.com` 的模式)和 `allowedHostnames`(精确主机例外,包括像 `localhost` 这样的被阻止名称)来设置显式例外。 -- 导航会在请求前检查,并在导航完成后的最终 `http(s)` URL 上尽力重新检查,以减少基于重定向的跳转。 +- 旧版别名:`browser.ssrfPolicy.allowPrivateNetwork` 仍会出于兼容性被接受。 +- 选择加入模式:设置 `browser.ssrfPolicy.dangerouslyAllowPrivateNetwork: true` 以允许私有/内部/特殊用途目标。 +- 在严格模式下,使用 `hostnameAllowlist`(如 `*.example.com` 的模式)和 `allowedHostnames`(精确主机例外,包括 `localhost` 等被阻止名称)来设置显式例外。 +- 导航会在请求前检查,并在导航后对最终 `http(s)` URL 尽力重新检查,以减少基于重定向的转向。 严格策略示例: -__OC_I18N_900017__ + +```json5 +{ + browser: { + ssrfPolicy: { + dangerouslyAllowPrivateNetwork: false, + hostnameAllowlist: ["*.example.com", "example.com"], + allowedHostnames: ["localhost"], + }, + }, +} +``` + ## 按智能体访问配置文件(多智能体) -通过多智能体路由,每个智能体都可以有自己的沙箱 + 工具策略: -用它为每个智能体授予**完整访问权限**、**只读权限**或**无访问权限**。 -参见[多智能体沙箱与工具](/tools/multi-agent-sandbox-tools)了解详情 -和优先级规则。 +通过多智能体路由,每个智能体都可以拥有自己的沙箱 + 工具策略: +用它为每个智能体提供**完全访问**、**只读**或**无访问**。 +完整详情和优先级规则见[多智能体沙箱与工具](/zh-CN/tools/multi-agent-sandbox-tools)。 常见用例: -- 个人智能体:完整访问权限,无沙箱 +- 个人智能体:完全访问,无沙箱 - 家庭/工作智能体:沙箱隔离 + 只读工具 - 公共智能体:沙箱隔离 + 无文件系统/shell 工具 -### 示例:完整访问权限(无沙箱) -__OC_I18N_900018__ +### 示例:完全访问(无沙箱) + +```json5 +{ + agents: { + list: [ + { + id: "personal", + workspace: "~/.openclaw/workspace-personal", + sandbox: { mode: "off" }, + }, + ], + }, +} +``` + ### 示例:只读工具 + 只读工作区 -__OC_I18N_900019__ -### 示例:无文件系统/shell 访问权限(允许提供商消息) -__OC_I18N_900020__ + +```json5 +{ + agents: { + list: [ + { + id: "family", + workspace: "~/.openclaw/workspace-family", + sandbox: { + mode: "all", + scope: "agent", + workspaceAccess: "ro", + }, + tools: { + allow: ["read"], + deny: ["write", "edit", "apply_patch", "exec", "process", "browser"], + }, + }, + ], + }, +} +``` + +### 示例:无文件系统/shell 访问(允许提供商消息传递) + +```json5 +{ + agents: { + list: [ + { + id: "public", + workspace: "~/.openclaw/workspace-public", + sandbox: { + mode: "all", + scope: "agent", + workspaceAccess: "none", + }, + // Session tools can reveal sensitive data from transcripts. By default OpenClaw limits these tools + // to the current session + spawned subagent sessions, but you can clamp further if needed. + // See `tools.sessions.visibility` in the configuration reference. + tools: { + sessions: { visibility: "tree" }, // self | tree | agent | all + allow: [ + "sessions_list", + "sessions_history", + "sessions_send", + "sessions_spawn", + "session_status", + "whatsapp", + "telegram", + "slack", + "discord", + ], + deny: [ + "read", + "write", + "edit", + "apply_patch", + "exec", + "process", + "browser", + "canvas", + "nodes", + "cron", + "gateway", + "image", + ], + }, + }, + ], + }, +} +``` + ## 事件响应 -如果你的 AI 做了不当操作: +如果你的 AI 做了不该做的事: ### 控制范围 1. **停止它:**停止 macOS 应用(如果它监管 Gateway 网关)或终止你的 `openclaw gateway` 进程。 -2. **关闭暴露面:**设置 `gateway.bind: "loopback"`(或禁用 Tailscale Funnel/Serve),直到你弄清发生了什么。 -3. **冻结访问:**将高风险私信/群组切换为 `dmPolicy: "disabled"` / 要求提及,并移除你曾设置的 `"*"` 全部允许条目。 +2. **关闭暴露面:**设置 `gateway.bind: "loopback"`(或禁用 Tailscale Funnel/Serve),直到你弄清楚发生了什么。 +3. **冻结访问:**将有风险的私信/群组切换为 `dmPolicy: "disabled"` / 要求提及,并移除你此前设置的 `"*"` 全部允许条目。 -### 轮换(如果秘密泄露,按已被攻破处理) +### 轮换(如果密钥泄露,假定已被攻破) 1. 轮换 Gateway 网关认证(`gateway.auth.token` / `OPENCLAW_GATEWAY_PASSWORD`)并重启。 -2. 在任何可以调用 Gateway 网关的机器上轮换远程客户端秘密(`gateway.remote.token` / `.password`)。 -3. 轮换提供商/API 凭据(WhatsApp 凭据、Slack/Discord 令牌、`auth-profiles.json` 中的模型/API key,以及使用时的加密秘密载荷值)。 +2. 在任何可以调用 Gateway 网关的机器上轮换远程客户端密钥(`gateway.remote.token` / `.password`)。 +3. 轮换提供商/API 凭证(WhatsApp 凭证、Slack/Discord 令牌、`auth-profiles.json` 中的模型/API key,以及使用时的加密密钥载荷值)。 ### 审计 1. 检查 Gateway 网关日志:`/tmp/openclaw/openclaw-YYYY-MM-DD.log`(或 `logging.file`)。 -2. 查看相关会话记录:`~/.openclaw/agents//sessions/*.jsonl`。 -3. 查看近期配置变更(任何可能扩大访问范围的内容:`gateway.bind`、`gateway.auth`、私信/群组策略、`tools.elevated`、插件变更)。 +2. 查看相关转录记录:`~/.openclaw/agents//sessions/*.jsonl`。 +3. 查看最近的配置更改(任何可能扩大访问范围的内容:`gateway.bind`、`gateway.auth`、私信/群组策略、`tools.elevated`、插件更改)。 4. 重新运行 `openclaw security audit --deep`,并确认关键发现已解决。 ### 收集报告材料 - 时间戳、Gateway 网关主机 OS + OpenClaw 版本 -- 会话记录 + 简短日志尾部(脱敏后) +- 会话转录记录 + 一小段日志尾部(脱敏后) - 攻击者发送了什么 + 智能体做了什么 - Gateway 网关是否暴露到 loopback 之外(LAN/Tailscale Funnel/Serve) -## 使用 detect-secrets 进行秘密扫描 +## 使用 detect-secrets 进行密钥扫描 CI 会在 `secrets` 作业中运行 `detect-secrets` pre-commit 钩子。 -推送到 `main` 始终会运行全文件扫描。拉取请求在有基准提交可用时使用变更文件 -快速路径,否则回退到全文件扫描。如果失败,说明存在尚未进入基线的新候选项。 +推送到 `main` 始终会运行全文件扫描。Pull request 在可用基准提交时使用变更文件 +快速路径,否则回退到全文件扫描。如果失败,说明存在尚未加入基线的新候选项。 ### 如果 CI 失败 1. 在本地复现: -__OC_I18N_900021__ -2. 了解这些工具: - - pre-commit 中的 `detect-secrets` 会使用仓库的 - 基线和排除项运行 `detect-secrets-hook`。 + + ```bash + pre-commit run --all-files detect-secrets + ``` + +2. 理解这些工具: + - pre-commit 中的 `detect-secrets` 会运行 `detect-secrets-hook`,并使用仓库的 + 基线和排除项。 - `detect-secrets audit` 会打开交互式审查,用于将每个基线 - 项标记为真实秘密或误报。 -3. 对于真实秘密:轮换/移除它们,然后重新运行扫描以更新基线。 -4. 对于误报:运行交互式审计并将它们标记为 false: -__OC_I18N_900022__ + 条目标记为真实或误报。 +3. 对于真实密钥:轮换/移除它们,然后重新运行扫描以更新基线。 +4. 对于误报:运行交互式审计并将其标记为 false: + + ```bash + detect-secrets audit .secrets.baseline + ``` + 5. 如果你需要新的排除项,请将其添加到 `.detect-secrets.cfg`,并使用匹配的 `--exclude-files` / `--exclude-lines` 标志重新生成基线(该配置 - 文件仅供参考;detect-secrets 不会自动读取它)。 + 文件仅作参考;detect-secrets 不会自动读取它)。 -当更新后的 `.secrets.baseline` 反映预期状态后,提交它。 +当更新后的 `.secrets.baseline` 反映预期状态后,将其提交。 ## 报告安全问题 -在 OpenClaw 中发现漏洞?请负责任地报告: +发现 OpenClaw 中的漏洞?请负责任地报告: -1. Email: [security@openclaw.ai](mailto:security@openclaw.ai) +1. 电子邮件:[security@openclaw.ai](mailto:security@openclaw.ai) 2. 修复前不要公开发布 -3. 我们会为你署名致谢(除非你希望匿名) +3. 我们会向你致谢(除非你希望匿名) diff --git a/docs/zh-CN/plugins/architecture.md b/docs/zh-CN/plugins/architecture.md index 06fe309cf..778ab99ec 100644 --- a/docs/zh-CN/plugins/architecture.md +++ b/docs/zh-CN/plugins/architecture.md @@ -1,29 +1,29 @@ --- read_when: - 构建或调试原生 OpenClaw 插件 - - 理解插件能力模型或所有权边界 - - 处理插件加载流水线或注册表时 + - 了解插件能力模型或所有权边界 + - 处理插件加载流水线或注册表 - 实现提供商运行时钩子或渠道插件 sidebarTitle: Internals summary: 插件内部机制:能力模型、所有权、契约、加载流水线和运行时辅助工具 title: 插件内部机制 x-i18n: - generated_at: "2026-04-29T02:56:07Z" + generated_at: "2026-05-01T21:07:54Z" model: gpt-5.5 provider: openai - source_hash: 1516e0784a005af87a6c081d8027a1e2dc10445e47b6824488e9d9987bb96975 + source_hash: ccca3a4ba5025793a85b496c0639c6b5baca362aecd642e93a0b833f01222559 source_path: plugins/architecture.md workflow: 16 --- -这是 OpenClaw 插件系统的**深度架构参考**。如需实践指南,请从下面的专题页面开始。 +这是 OpenClaw 插件系统的**深度架构参考**。实用指南请从下面的专题页面开始。 - - 面向最终用户的指南,用于添加、启用插件并进行故障排除。 + + 面向最终用户的指南,用于添加、启用和排查插件问题。 - 使用最小可用清单创建第一个插件的教程。 + 第一个插件教程,包含最小可用清单。 构建一个消息渠道插件。 @@ -38,7 +38,7 @@ x-i18n: ## 公共能力模型 -能力是 OpenClaw 内部公开的**原生插件**模型。每个原生 OpenClaw 插件都会注册到一种或多种能力类型: +能力是 OpenClaw 内部的公共**原生插件**模型。每个原生 OpenClaw 插件都会针对一个或多个能力类型注册: | 能力 | 注册方法 | 示例插件 | | ---------------------- | ------------------------------------------------ | ------------------------------------ | @@ -54,27 +54,27 @@ x-i18n: | Web 获取 | `api.registerWebFetchProvider(...)` | `firecrawl` | | Web 搜索 | `api.registerWebSearchProvider(...)` | `google` | | 渠道 / 消息 | `api.registerChannel(...)` | `msteams`, `matrix` | -| Gateway 网关设备发现 | `api.registerGatewayDiscoveryService(...)` | `bonjour` | +| Gateway 网关发现 | `api.registerGatewayDiscoveryService(...)` | `bonjour` | -注册零项能力但提供钩子、工具、设备发现服务或后台服务的插件是**仅旧版钩子**插件。这种模式仍然受到完整支持。 +注册零个能力但提供钩子、工具、发现服务或后台服务的插件是**旧版纯钩子**插件。该模式仍然完全受支持。 ### 外部兼容性立场 -能力模型已经落地到核心中,并且目前由内置/原生插件使用,但外部插件兼容性仍需要比“已导出,因此已冻结”更严格的标准。 +能力模型已经落入核心,并且今天由内置 / 原生插件使用,但外部插件兼容性仍需要比“它已导出,所以已经冻结”更严格的标准。 -| 插件情况 | 指导建议 | +| 插件情况 | 指引 | | ------------------------------------------------- | ------------------------------------------------------------------------------------------------ | | 现有外部插件 | 保持基于钩子的集成可用;这是兼容性基线。 | -| 新的内置/原生插件 | 优先使用显式能力注册,而不是供应商特定的直接访问或新的仅钩子设计。 | -| 采用能力注册的外部插件 | 允许使用,但除非文档标明稳定,否则应将能力特定的辅助接口视为仍在演进。 | +| 新的内置 / 原生插件 | 优先使用显式能力注册,而不是供应商特定的内部访问或新的纯钩子设计。 | +| 采用能力注册的外部插件 | 允许这样做,但除非文档标记为稳定,否则应将能力特定的辅助接口视为仍在演进。 | -能力注册是预期方向。在过渡期间,旧版钩子仍然是外部插件最安全的无破坏路径。导出的辅助子路径并不完全等价——优先使用范围狭窄且已文档化的契约,而不是偶然导出的辅助接口。 +能力注册是预期方向。在过渡期间,旧版钩子仍然是外部插件最安全的无破坏路径。导出的辅助子路径并不都等价——优先使用狭窄且有文档说明的契约,而不是偶然导出的辅助接口。 ### 插件形态 -OpenClaw 会根据每个已加载插件的实际注册行为(而不仅仅是静态元数据)将其归类为一种形态: +OpenClaw 会根据每个已加载插件的实际注册行为(不只是静态元数据)将其分类为一种形态: @@ -84,81 +84,81 @@ OpenClaw 会根据每个已加载插件的实际注册行为(而不仅仅是 注册多种能力类型(例如 `openai` 拥有文本推理、语音、媒体理解和图像生成)。 - 只注册钩子(类型化或自定义),没有能力、工具、命令或服务。 + 只注册钩子(类型化或自定义),不注册能力、工具、命令或服务。 - 注册工具、命令、服务或路由,但没有能力。 + 注册工具、命令、服务或路由,但不注册能力。 -使用 `openclaw plugins inspect ` 查看插件的形态和能力拆解。详见 [CLI 参考](/zh-CN/cli/plugins#inspect)。 +使用 `openclaw plugins inspect ` 查看插件的形态和能力明细。详情请参阅 [CLI 参考](/zh-CN/cli/plugins#inspect)。 ### 旧版钩子 -`before_agent_start` 钩子仍作为仅钩子插件的兼容路径受到支持。真实世界中的旧版插件仍依赖它。 +`before_agent_start` 钩子仍作为纯钩子插件的兼容路径受到支持。旧版真实世界插件仍依赖它。 方向: - 保持其可用 -- 将其文档化为旧版机制 -- 对模型/提供商覆盖工作,优先使用 `before_model_resolve` -- 对提示词变更工作,优先使用 `before_prompt_build` -- 只有在真实使用量下降且 fixture 覆盖证明迁移安全后才移除 +- 将其记录为旧版机制 +- 对于模型 / 提供商覆盖工作,优先使用 `before_model_resolve` +- 对于提示词变更工作,优先使用 `before_prompt_build` +- 只有在真实使用量下降且夹具覆盖证明迁移安全之后才移除 ### 兼容性信号 运行 `openclaw doctor` 或 `openclaw plugins inspect ` 时,你可能会看到以下标签之一: -| 信号 | 含义 | -| -------------------------- | ---------------------------------------------------------- | -| **配置有效** | 配置可以正常解析,插件也能解析 | -| **兼容性建议** | 插件使用受支持但较旧的模式(例如 `hook-only`) | -| **旧版警告** | 插件使用已弃用的 `before_agent_start` | -| **硬错误** | 配置无效,或插件加载失败 | +| 信号 | 含义 | +| ---------------------------- | ------------------------------------------------------------ | +| **配置有效** | 配置解析正常,插件也能解析 | +| **兼容性建议** | 插件使用受支持但较旧的模式(例如 `hook-only`) | +| **旧版警告** | 插件使用已弃用的 `before_agent_start` | +| **硬错误** | 配置无效,或插件加载失败 | -`hook-only` 和 `before_agent_start` 目前都不会破坏你的插件:`hook-only` 只是建议,`before_agent_start` 只会触发警告。这些信号也会出现在 `openclaw status --all` 和 `openclaw plugins doctor` 中。 +今天,`hook-only` 和 `before_agent_start` 都不会破坏你的插件:`hook-only` 只是建议性信号,而 `before_agent_start` 只会触发警告。这些信号也会出现在 `openclaw status --all` 和 `openclaw plugins doctor` 中。 ## 架构概览 OpenClaw 的插件系统有四层: - - OpenClaw 会从已配置路径、工作区根目录、全局插件根目录和内置插件中查找候选插件。设备发现会先读取原生 `openclaw.plugin.json` 清单以及受支持的 bundle 清单。 + + OpenClaw 会从配置的路径、工作区根目录、全局插件根目录和内置插件中查找候选插件。发现过程会先读取原生 `openclaw.plugin.json` 清单以及受支持的包清单。 - 核心会决定发现的插件是启用、禁用、阻止,还是被选中用于某个独占槽位,例如 memory。 + 核心会决定已发现的插件是启用、禁用、阻止,还是被选为内存等独占槽位。 - 原生 OpenClaw 插件通过 jiti 在进程内加载,并将能力注册到中央注册表。兼容 bundle 会被规范化为注册表记录,而不会导入运行时代码。 + 原生 OpenClaw 插件会在进程内加载,并将能力注册到中央注册表中。打包的 JavaScript 通过原生 `require` 加载;源码 TypeScript 会回退到 Jiti。兼容包会被规范化为注册表记录,而不会导入运行时代码。 - OpenClaw 的其余部分会读取注册表,以暴露工具、渠道、提供商设置、钩子、HTTP 路由、CLI 命令和服务。 + OpenClaw 的其余部分读取注册表,以暴露工具、渠道、提供商设置、钩子、HTTP 路由、CLI 命令和服务。 -对于插件 CLI,根命令设备发现特别分为两个阶段: +对于插件 CLI,根命令发现专门分为两个阶段: - 解析时元数据来自 `registerCli(..., { descriptors: [...] })` -- 真实的插件 CLI 模块可以保持懒加载,并在首次调用时注册 +- 真实的插件 CLI 模块可以保持惰性,并在首次调用时注册 -这样既能将插件拥有的 CLI 代码保留在插件内部,又能让 OpenClaw 在解析前保留根命令名称。 +这让插件拥有的 CLI 代码仍位于插件内部,同时仍允许 OpenClaw 在解析前保留根命令名称。 重要的设计边界: -- 清单/配置验证应当能够基于**清单/schema 元数据**完成,而不执行插件代码 -- 原生能力发现可以加载可信插件入口代码,以构建一个不会激活的注册表快照 +- 清单 / 配置验证应该能基于**清单 / schema 元数据**完成,而不执行插件代码 +- 原生能力发现可以加载受信任的插件入口代码,以构建非激活注册表快照 - 原生运行时行为来自插件模块的 `register(api)` 路径,并且 `api.registrationMode === "full"` -这种拆分让 OpenClaw 可以在完整运行时激活前验证配置、解释缺失/禁用的插件,并构建 UI/schema 提示。 +这种拆分让 OpenClaw 能在完整运行时激活前验证配置、解释缺失 / 已禁用插件,并构建 UI / schema 提示。 ### 插件元数据快照和查找表 -Gateway 网关启动时会为当前配置快照构建一个 `PluginMetadataSnapshot`。该快照仅包含元数据:它存储已安装插件索引、清单注册表、清单诊断、所有者映射、插件 ID 规范化器和清单记录。它不持有已加载的插件模块、提供商 SDK、包内容或运行时导出。 +Gateway 网关启动时会为当前配置快照构建一个 `PluginMetadataSnapshot`。该快照只包含元数据:它存储已安装插件索引、清单注册表、清单诊断信息、所有者映射、插件 ID 规范化器和清单记录。它不保存已加载的插件模块、提供商 SDK、包内容或运行时导出。 -感知插件的配置验证、启动自动启用和 Gateway 网关插件引导会消费该快照,而不是各自独立重建清单/索引元数据。`PluginLookUpTable` 派生自同一个快照,并为当前运行时配置添加启动插件计划。 +感知插件的配置验证、启动自动启用和 Gateway 网关插件引导会消费该快照,而不是各自独立重建清单 / 索引元数据。`PluginLookUpTable` 派生自同一个快照,并为当前运行时配置添加启动插件计划。 -启动后,Gateway 网关会将当前元数据快照保留为可替换的运行时产物。重复的运行时提供商设备发现可以借用该快照,而不必为每次提供商目录遍历重新构建已安装索引和清单注册表。Gateway 网关关闭、配置/插件清单变化以及已安装索引写入时,该快照会被清除或替换;如果不存在兼容的当前快照,调用方会回退到冷启动清单/索引路径。兼容性检查必须包含插件设备发现根目录,例如 `plugins.load.paths` 和默认 Agent 工作区,因为工作区插件属于元数据范围的一部分。 +启动后,Gateway 网关会将当前元数据快照保留为可替换的运行时产物。重复的运行时提供商发现可以借用该快照,而不是在每次提供商目录遍历时重建已安装索引和清单注册表。Gateway 网关关闭、配置 / 插件清单变化以及已安装索引写入时,会清除或替换该快照;如果不存在兼容的当前快照,调用方会回退到冷清单 / 索引路径。兼容性检查必须包含插件发现根目录,例如 `plugins.load.paths` 和默认 Agent 工作区,因为工作区插件属于元数据范围。 快照和查找表让重复的启动决策保持在快速路径上: @@ -170,11 +170,11 @@ Gateway 网关启动时会为当前配置快照构建一个 `PluginMetadataSnaps - 插件配置 schema 和渠道配置 schema 验证 - 启动自动启用决策 -安全边界是快照替换,而不是突变。配置、插件清单、安装记录或持久化索引策略变化时,应重建快照。不要把它当作广泛可变的全局注册表,也不要保留无界历史快照。运行时插件加载仍与元数据快照分离,因此过期的运行时状态不能隐藏在元数据缓存后面。 +安全边界是快照替换,而不是变更。配置、插件清单、安装记录或持久化索引策略变化时,应重建快照。不要将它视为广泛可变的全局注册表,也不要保留无界历史快照。运行时插件加载仍与元数据快照分离,因此陈旧的运行时状态无法隐藏在元数据缓存之后。 -缓存规则记录在[插件架构内部机制](/zh-CN/plugins/architecture-internals#plugin-cache-boundary):除非调用方持有当前流程的显式快照、查找表或清单注册表,否则清单和设备发现元数据始终是新鲜的。隐藏元数据缓存和墙钟 TTL 并不是插件加载的一部分。只有运行时加载器、模块和依赖制品缓存可以在代码或已安装制品实际加载后持续存在。 +缓存规则记录在[插件架构内部机制](/zh-CN/plugins/architecture-internals#plugin-cache-boundary)中:除非调用方持有当前流程的显式快照、查找表或清单注册表,否则清单和发现元数据都是新鲜的。隐藏元数据缓存和挂钟 TTL 不属于插件加载的一部分。只有在代码或已安装构件实际加载之后,运行时加载器、模块和依赖构件缓存才可以持续存在。 -一些冷路径调用方仍会直接从持久化的已安装插件索引重建清单注册表,而不是接收 Gateway 网关 `PluginLookUpTable`。该路径现在会按需重建注册表;如果调用方已经有当前查找表或显式清单注册表,运行时流程中应优先传递它们。 +一些冷路径调用方仍会直接从持久化的已安装插件索引重建清单注册表,而不是接收 Gateway 网关的 `PluginLookUpTable`。该路径现在会按需重建注册表;如果调用方已有当前查找表或显式清单注册表,优先将其通过运行时流程传递。 ### 激活规划 @@ -184,27 +184,27 @@ Gateway 网关启动时会为当前配置快照构建一个 `PluginMetadataSnaps - `activation.*` 字段是显式规划器提示 - `providers`、`channels`、`commandAliases`、`setup.providers`、`contracts.tools` 和钩子仍作为清单所有权回退 -- 仅 ID 的规划器 API 仍可供现有调用方使用 -- 计划 API 会报告原因标签,因此诊断可以区分显式提示和所有权回退 +- 仅 ID 的规划器 API 仍供现有调用方使用 +- 计划 API 会报告原因标签,因此诊断信息可以区分显式提示和所有权回退 -不要把 `activation` 当作生命周期钩子或 `register(...)` 的替代品。它是用于缩小加载范围的元数据。当所有权字段已经描述了关系时,优先使用所有权字段;仅将 `activation` 用作额外的规划器提示。 +不要把 `activation` 当作生命周期钩子,也不要把它当作 `register(...)` 的替代品。它是用于缩小加载范围的元数据。当所有权字段已经描述了这种关系时,优先使用所有权字段;仅将 `activation` 用作额外的规划器提示。 -### 渠道插件和共享消息工具 +### 渠道插件与共享消息工具 -渠道插件不需要为常规聊天操作注册单独的发送、编辑或反应工具。OpenClaw 在核心中保留一个共享的 `message` 工具,而渠道插件拥有其背后的渠道特定发现和执行逻辑。 +渠道插件不需要为普通聊天操作注册单独的发送、编辑或回应工具。OpenClaw 在核心中保留一个共享的 `message` 工具,而渠道插件拥有其背后的渠道特定设备发现和执行逻辑。 当前边界是: -- 核心拥有共享的 `message` 工具宿主、提示词接线、会话/线程记账以及执行分发 -- 渠道插件拥有作用域内的动作发现、能力发现以及任何渠道特定的 schema 片段 -- 渠道插件拥有提供商特定的会话对话语法,例如会话 ID 如何编码线程 ID 或从父会话继承 -- 渠道插件通过其动作适配器执行最终动作 +- 核心拥有共享 `message` 工具宿主、提示词接线、会话/线程记账,以及执行分派 +- 渠道插件拥有作用域内的操作发现、能力发现,以及任何渠道特定的 schema 片段 +- 渠道插件拥有提供商特定的会话对话语法,例如对话 ID 如何编码线程 ID,或如何从父级对话继承 +- 渠道插件通过它们的操作适配器执行最终操作 -对于渠道插件,SDK 表面是 `ChannelMessageActionAdapter.describeMessageTool(...)`。这个统一的发现调用允许插件一起返回其可见动作、能力和 schema 贡献,从而避免这些部分彼此漂移。 +对于渠道插件,SDK 表面是 `ChannelMessageActionAdapter.describeMessageTool(...)`。这个统一发现调用让插件能够一起返回其可见操作、能力和 schema 贡献,从而避免这些部分彼此漂移。 -当渠道特定的消息工具参数携带媒体源(例如本地路径或远程媒体 URL)时,插件还应从 `describeMessageTool(...)` 返回 `mediaSourceParams`。核心使用这个显式列表来应用沙箱路径规范化和出站媒体访问提示,而无需硬编码插件拥有的参数名称。这里优先使用按动作划分的映射,而不是一个渠道级的扁平列表,这样仅用于资料的媒体参数就不会在 `send` 等无关动作上被规范化。 +当渠道特定的消息工具参数携带媒体来源(例如本地路径或远程媒体 URL)时,插件还应从 `describeMessageTool(...)` 返回 `mediaSourceParams`。核心使用这个显式列表来应用沙箱路径规范化和出站媒体访问提示,而不需要硬编码插件拥有的参数名称。这里优先使用按操作限定作用域的映射,而不是一个渠道范围的扁平列表,这样仅用于资料的媒体参数就不会在 `send` 等无关操作上被规范化。 核心会把运行时作用域传入该发现步骤。重要字段包括: @@ -217,106 +217,106 @@ Gateway 网关启动时会为当前配置快照构建一个 `PluginMetadataSnaps - `agentId` - 受信任的入站 `requesterSenderId` -这对上下文敏感的插件很重要。渠道可以基于当前账号、当前房间/线程/消息或受信任的请求者身份来隐藏或公开消息动作,而无需在核心 `message` 工具中硬编码渠道特定分支。 +这对上下文敏感的插件很重要。渠道可以根据活跃账号、当前房间/线程/消息,或受信任的请求者身份隐藏或暴露消息操作,而无需在核心 `message` 工具中硬编码渠道特定分支。 -这就是为什么嵌入式 runner 路由变更仍然是插件工作的原因:runner 负责把当前聊天/会话身份转发到插件发现边界中,使共享的 `message` 工具能够为当前轮次公开正确的渠道拥有表面。 +这就是为什么嵌入式运行器路由变更仍然属于插件工作:运行器负责把当前聊天/会话身份转发到插件发现边界,让共享 `message` 工具为当前轮次暴露正确的渠道拥有表面。 -对于渠道拥有的执行辅助工具,内置插件应将执行运行时保留在自己的扩展模块内。核心不再在 `src/agents/tools` 下拥有 Discord、Slack、Telegram 或 WhatsApp 消息动作运行时。我们不会发布单独的 `plugin-sdk/*-action-runtime` 子路径,内置插件应直接从其扩展拥有的模块导入自己的本地运行时代码。 +对于渠道拥有的执行辅助函数,内置插件应将执行运行时保留在自己的 extension 模块中。核心不再在 `src/agents/tools` 下拥有 Discord、Slack、Telegram 或 WhatsApp 消息操作运行时。我们不会发布单独的 `plugin-sdk/*-action-runtime` 子路径,内置插件应直接从其 extension 拥有的模块导入自己的本地运行时代码。 -同样的边界也适用于一般的提供商命名 SDK 接缝:核心不应为 Slack、Discord、Signal、WhatsApp 或类似扩展导入渠道特定的便捷 barrel。如果核心需要某种行为,要么消费内置插件自己的 `api.ts` / `runtime-api.ts` barrel,要么把需求提升为共享 SDK 中狭窄的通用能力。 +同样的边界也适用于一般的提供商命名 SDK 接缝:核心不应为 Slack、Discord、Signal、WhatsApp 或类似 extensions 导入渠道特定的便利 barrel。如果核心需要某种行为,要么消费内置插件自己的 `api.ts` / `runtime-api.ts` barrel,要么把需求提升为共享 SDK 中狭窄的通用能力。 -内置插件遵循相同规则。内置插件的 `runtime-api.ts` 不应重新导出自己的品牌化 `openclaw/plugin-sdk/` facade。这些品牌化 facade 仍然是面向外部插件和旧消费者的兼容性 shim,但内置插件应使用本地导出加上狭窄的通用 SDK 子路径,例如 `openclaw/plugin-sdk/channel-policy`、`openclaw/plugin-sdk/runtime-store` 或 `openclaw/plugin-sdk/webhook-ingress`。新代码不应添加插件 ID 特定的 SDK facade,除非现有外部生态的兼容性边界需要它。 +内置插件遵循相同规则。内置插件的 `runtime-api.ts` 不应重新导出自己带品牌的 `openclaw/plugin-sdk/` facade。这些带品牌的 facade 仍然是供外部插件和旧消费者使用的兼容性 shim,但内置插件应使用本地导出,以及狭窄的通用 SDK 子路径,例如 `openclaw/plugin-sdk/channel-policy`、`openclaw/plugin-sdk/runtime-store` 或 `openclaw/plugin-sdk/webhook-ingress`。新代码不应添加插件 ID 特定的 SDK facade,除非现有外部生态系统的兼容性边界需要它。 -对于投票,具体有两条执行路径: +特别是对于投票,有两条执行路径: - `outbound.sendPoll` 是适合通用投票模型的渠道的共享基线 -- `actions.handleAction("poll")` 是渠道特定投票语义或额外投票参数的首选路径 +- `actions.handleAction("poll")` 是用于渠道特定投票语义或额外投票参数的首选路径 -核心现在会将共享投票解析延后到插件投票分发拒绝该动作之后,因此插件拥有的投票处理器可以接受渠道特定的投票字段,而不会先被通用投票解析器阻挡。 +核心现在会等到插件投票分派拒绝操作之后,才执行共享投票解析,因此插件拥有的投票处理器可以接受渠道特定的投票字段,而不会先被通用投票解析器阻挡。 完整启动序列见 [插件架构内部机制](/zh-CN/plugins/architecture-internals)。 ## 能力所有权模型 -OpenClaw 将原生插件视为一个**公司**或一个**功能**的所有权边界,而不是一堆无关集成的大杂烩。 +OpenClaw 将原生插件视为一个**公司**或一项**功能**的所有权边界,而不是一堆无关集成的集合。 这意味着: - 公司插件通常应拥有该公司面向 OpenClaw 的所有表面 - 功能插件通常应拥有它引入的完整功能表面 -- 渠道应消费共享核心能力,而不是临时重新实现提供商行为 +- 渠道应消费共享的核心能力,而不是临时重新实现提供商行为 - - `openai` 拥有文本推理、语音、实时语音、媒体理解和图像生成。`google` 拥有文本推理以及媒体理解、图像生成和 Web 搜索。`qwen` 拥有文本推理以及媒体理解和视频生成。 + + `openai` 拥有文本推理、语音、实时语音、媒体理解和图像生成。`google` 拥有文本推理,以及媒体理解、图像生成和 Web 搜索。`qwen` 拥有文本推理,以及媒体理解和视频生成。 - - `elevenlabs` 和 `microsoft` 拥有语音;`firecrawl` 拥有 Web 获取;`minimax` / `mistral` / `moonshot` / `zai` 拥有媒体理解后端。 + + `elevenlabs` 和 `microsoft` 拥有语音;`firecrawl` 拥有 Web 抓取;`minimax` / `mistral` / `moonshot` / `zai` 拥有媒体理解后端。 - `voice-call` 拥有呼叫传输、工具、CLI、路由和 Twilio 媒体流桥接,但消费共享的语音、实时转录和实时语音能力,而不是直接导入厂商插件。 + `voice-call` 拥有通话传输、工具、CLI、路由和 Twilio 媒体流桥接,但会消费共享语音、实时转写和实时语音能力,而不是直接导入供应商插件。 预期的最终状态是: -- OpenAI 存在于一个插件中,即使它横跨文本模型、语音、图像和未来的视频 -- 另一个厂商可以对自己的表面区域执行相同做法 -- 渠道不关心哪个厂商插件拥有提供商;它们消费核心公开的共享能力契约 +- 即使 OpenAI 跨越文本模型、语音、图像和未来视频,也仍然位于一个插件中 +- 另一个供应商也可以对自己的表面区域采用同样方式 +- 渠道不关心哪个供应商插件拥有该提供商;它们消费核心暴露的共享能力合约 -关键区别是: +这是关键区别: - **插件** = 所有权边界 -- **能力** = 多个插件可以实现或消费的核心契约 +- **能力** = 多个插件可以实现或消费的核心合约 -因此,如果 OpenClaw 添加了一个新领域(例如视频),第一个问题不是“哪个提供商应硬编码视频处理?”第一个问题是“核心视频能力契约是什么?”一旦该契约存在,厂商插件就可以针对它注册,渠道/功能插件也可以消费它。 +因此,如果 OpenClaw 添加一个新领域(例如视频),第一个问题不是“哪个提供商应该硬编码视频处理?”第一个问题是“核心视频能力合约是什么?”一旦该合约存在,供应商插件就可以针对它注册,渠道/功能插件也可以消费它。 -如果能力尚不存在,正确做法通常是: +如果该能力尚不存在,正确做法通常是: 在核心中定义缺失的能力。 - - 以类型化方式通过插件 API/运行时公开它。 + + 以类型化方式通过插件 API/运行时暴露它。 将渠道/功能接线到该能力。 - - 让厂商插件注册实现。 + + 让供应商插件注册实现。 -这会保持所有权明确,同时避免核心行为依赖单个厂商或一次性的插件特定代码路径。 +这会保持所有权明确,同时避免核心行为依赖单一供应商或一次性的插件特定代码路径。 ### 能力分层 -在决定代码归属位置时使用这个心智模型: +在决定代码归属时,使用这个思维模型: - 共享编排、策略、回退、配置合并规则、交付语义和类型化契约。 + 共享编排、策略、回退、配置合并规则、交付语义和类型化合约。 - - 厂商特定 API、认证、模型目录、语音合成、图像生成、未来视频后端、用量端点。 + + 供应商特定 API、认证、模型目录、语音合成、图像生成、未来视频后端、用量端点。 - Slack/Discord/voice-call/等集成,消费核心能力并在某个表面上呈现它们。 + 消费核心能力并在某个表面上呈现这些能力的 Slack/Discord/voice-call 等集成。 -例如,TTS 遵循这种形态: +例如,TTS 遵循这种形状: -- 核心拥有回复时 TTS 策略、回退顺序、偏好和渠道交付 +- 核心拥有回复时 TTS 策略、回退顺序、偏好设置和渠道交付 - `openai`、`elevenlabs` 和 `microsoft` 拥有合成实现 -- `voice-call` 消费电话 TTS 运行时辅助工具 +- `voice-call` 消费电话 TTS 运行时辅助函数 -同样的模式应优先用于未来能力。 +未来能力也应优先采用同样模式。 ### 多能力公司插件示例 -公司插件从外部看应当是内聚的。如果 OpenClaw 对模型、语音、实时转录、实时语音、媒体理解、图像生成、视频生成、Web 获取和 Web 搜索都有共享契约,厂商就可以在一个地方拥有它的所有表面: +公司插件从外部看应当是内聚的。如果 OpenClaw 为模型、语音、实时转写、实时语音、媒体理解、图像生成、视频生成、Web 抓取和 Web 搜索提供共享合约,供应商就可以在一个地方拥有自己的全部表面: ```ts import type { OpenClawPluginDefinition } from "openclaw/plugin-sdk/plugin-entry"; @@ -370,116 +370,116 @@ const plugin: OpenClawPluginDefinition = { export default plugin; ``` -重要的不是确切的辅助工具名称,而是形态: +重要的不是确切的辅助函数名称。重要的是形状: -- 一个插件拥有厂商表面 -- 核心仍然拥有能力契约 -- 渠道和功能插件消费 `api.runtime.*` 辅助工具,而不是厂商代码 -- 契约测试可以断言该插件注册了它声称拥有的能力 +- 一个插件拥有供应商表面 +- 核心仍然拥有能力合约 +- 渠道和功能插件消费 `api.runtime.*` 辅助函数,而不是供应商代码 +- 合约测试可以断言该插件注册了它声称拥有的能力 ### 能力示例:视频理解 -OpenClaw 已经将图像/音频/视频理解视为一个共享能力。相同的所有权模型也适用于那里: +OpenClaw 已经把图像/音频/视频理解视为一个共享能力。同样的所有权模型也适用于那里: - - 核心定义媒体理解契约。 + + 核心定义媒体理解合约。 - - 厂商插件按需注册 `describeImage`、`transcribeAudio` 和 `describeVideo`。 + + 供应商插件按适用情况注册 `describeImage`、`transcribeAudio` 和 `describeVideo`。 - 渠道和功能插件消费共享的核心行为,而不是直接接线到厂商代码。 + 渠道和功能插件消费共享核心行为,而不是直接接线到供应商代码。 -这避免把某个提供商的视频假设固化到核心中。插件拥有厂商表面;核心拥有能力契约和回退行为。 +这避免把某个提供商的视频假设烘焙进核心。插件拥有供应商表面;核心拥有能力合约和回退行为。 -视频生成已经使用相同序列:核心拥有类型化能力契约和运行时辅助工具,厂商插件针对它注册 `api.registerVideoGenerationProvider(...)` 实现。 +视频生成已经使用同样的序列:核心拥有类型化能力合约和运行时辅助函数,供应商插件针对它注册 `api.registerVideoGenerationProvider(...)` 实现。 -需要具体的推出检查清单?见 [能力扩展手册](/zh-CN/plugins/architecture)。 +需要具体的发布清单?见 [能力扩展手册](/zh-CN/plugins/architecture)。 -## 契约和强制执行 +## 合约与强制执行 -插件 API 表面有意在 `OpenClawPluginApi` 中保持类型化和集中化。该契约定义受支持的注册点以及插件可以依赖的运行时辅助工具。 +插件 API 表面有意集中在 `OpenClawPluginApi` 中并提供类型。该合约定义了受支持的注册点,以及插件可以依赖的运行时辅助函数。 这很重要,因为: - 插件作者获得一个稳定的内部标准 -- 核心可以拒绝重复所有权,例如两个插件注册同一个提供商 ID -- 启动可以为格式错误的注册公开可操作的诊断信息 -- 契约测试可以强制执行内置插件所有权并防止静默漂移 +- 核心可以拒绝重复所有权,例如两个插件注册相同的提供商 ID +- 启动可以为格式错误的注册暴露可操作诊断 +- 合约测试可以强制执行内置插件所有权,并防止静默漂移 -有两层强制执行: +强制执行有两层: - - 插件注册表会在插件加载时验证注册。示例:重复的提供商 ID、重复的语音提供商 ID,以及格式错误的注册会产生插件诊断,而不是未定义行为。 + + 插件注册表会在插件加载时验证注册。示例:重复的提供商 ID、重复的语音提供商 ID,以及格式错误的注册都会产生插件诊断信息,而不是未定义行为。 - 内置插件会在测试运行期间被捕获到契约注册表中,以便 OpenClaw 可以明确断言所有权。目前,这用于模型提供商、语音提供商、Web 搜索提供商,以及内置注册所有权。 + 内置插件会在测试运行期间被捕获到契约注册表中,以便 OpenClaw 可以显式断言所有权。目前这用于模型提供商、语音提供商、Web 搜索提供商,以及内置注册所有权。 -实际效果是,OpenClaw 会预先知道哪个插件拥有哪个表面。这让 core 和渠道能够无缝组合,因为所有权是声明式、类型化且可测试的,而不是隐式的。 +实际效果是,OpenClaw 会预先知道哪个插件拥有哪个表面。这让核心和渠道可以无缝组合,因为所有权是声明式、有类型且可测试的,而不是隐式的。 ### 契约中应包含什么 - - 类型化 - - 小而聚焦 - - 面向特定能力 - - 由 core 拥有 + - 有类型 + - 小而精 + - 特定于能力 + - 由核心拥有 - 可被多个插件复用 - - 可被渠道/功能使用,且不需要厂商知识 + - 可被渠道/功能使用,而不需要了解供应商 - - 隐藏在 core 中的厂商特定策略 + - 隐藏在核心中的供应商特定策略 - 绕过注册表的一次性插件逃生口 - - 渠道代码直接访问厂商实现 + - 渠道代码直接访问供应商实现 - 不属于 `OpenClawPluginApi` 或 `api.runtime` 的临时运行时对象 -拿不准时,提高抽象层级:先定义能力,再让插件接入它。 +有疑问时,提高抽象层级:先定义能力,再让插件接入它。 ## 执行模型 -原生 OpenClaw 插件会与 Gateway 网关**在同一进程内**运行。它们没有经过沙箱隔离。已加载的原生插件与 core 代码具有相同的进程级信任边界。 +原生 OpenClaw 插件会与 Gateway 网关**在同一进程中**运行。它们不是沙箱隔离的。已加载的原生插件与核心代码具有相同的进程级信任边界。 -原生插件的影响:插件可以注册工具、网络处理程序、钩子和服务;插件 bug 可能导致 Gateway 网关崩溃或不稳定;恶意原生插件等同于在 OpenClaw 进程内执行任意代码。 +原生插件的影响:插件可以注册工具、网络处理程序、钩子和服务;插件错误可能导致 Gateway 网关崩溃或不稳定;恶意原生插件等同于在 OpenClaw 进程内执行任意代码。 -兼容包默认更安全,因为 OpenClaw 目前会将它们视为元数据/内容包。在当前版本中,这主要意味着内置 Skills。 +兼容包默认更安全,因为 OpenClaw 当前会将它们视为元数据/内容包。在当前版本中,这主要意味着内置 Skills。 -对于非内置插件,请使用允许列表和显式安装/加载路径。将工作区插件视为开发时代码,而不是生产默认项。 +对非内置插件使用允许列表和显式安装/加载路径。将工作区插件视为开发时代码,而不是生产默认项。 -对于内置工作区包名称,默认让插件 ID 锚定在 npm 名称中:`@openclaw/`,或者在包有意暴露更窄插件角色时使用经批准的类型化后缀,例如 `-provider`、`-plugin`、`-speech`、`-sandbox` 或 `-media-understanding`。 +对于内置工作区包名,默认将插件 ID 锚定到 npm 名称:`@openclaw/`,或者在包有意暴露更窄插件角色时使用已批准的类型化后缀,例如 `-provider`、`-plugin`、`-speech`、`-sandbox` 或 `-media-understanding`。 -**信任说明:**`plugins.allow` 信任的是**插件 ID**,而不是来源。与内置插件具有相同 ID 的工作区插件,在该工作区插件被启用/加入允许列表时,会有意遮蔽内置副本。这是正常行为,并且对本地开发、补丁测试和热修复很有用。内置插件信任来自源快照,也就是加载时磁盘上的清单和代码,而不是安装元数据。损坏或被替换的安装记录不能静默扩大内置插件的信任表面,使其超出实际源代码声明的范围。 +**信任说明:**`plugins.allow` 信任的是**插件 ID**,而不是来源出处。当某个工作区插件启用/列入允许列表,并且与内置插件具有相同 ID 时,它会有意遮蔽内置副本。这是正常行为,并且对本地开发、补丁测试和热修复很有用。内置插件信任是根据源快照解析的,也就是加载时磁盘上的清单和代码,而不是根据安装元数据解析。损坏或被替换的安装记录不能悄悄把内置插件的信任表面扩大到实际源代码声明之外。 ## 导出边界 OpenClaw 导出能力,而不是实现便利项。 -保持能力注册为公开接口。裁剪非契约辅助导出: +保持能力注册为公开。裁剪非契约辅助导出: - 内置插件特定的辅助子路径 - 不打算作为公共 API 的运行时管道子路径 -- 厂商特定的便利辅助函数 +- 供应商特定的便利辅助函数 - 属于实现细节的设置/新手引导辅助函数 -保留的内置插件辅助子路径已从生成的 SDK 导出映射中移除。将所有者特定的辅助函数保留在所属插件包内;只将可复用的宿主行为提升为通用 SDK 契约,例如 `plugin-sdk/gateway-runtime`、`plugin-sdk/security-runtime` 和 `plugin-sdk/plugin-config-runtime`。 +保留的内置插件辅助子路径已从生成的 SDK 导出映射中退役。将所有者特定的辅助函数保留在所属插件包内;只将可复用的主机行为提升为通用 SDK 契约,例如 `plugin-sdk/gateway-runtime`、`plugin-sdk/security-runtime` 和 `plugin-sdk/plugin-config-runtime`。 -## 内部机制与参考 +## 内部机制和参考 -有关加载流水线、注册表模型、提供商运行时钩子、Gateway 网关 HTTP 路由、消息工具 schema、渠道目标解析、提供商目录、上下文引擎插件,以及添加新能力的指南,请参阅[插件架构内部机制](/zh-CN/plugins/architecture-internals)。 +有关加载流水线、注册表模型、提供商运行时钩子、Gateway 网关 HTTP 路由、消息工具 schema、渠道目标解析、提供商目录、上下文引擎插件,以及新增能力指南,请参阅[插件架构内部机制](/zh-CN/plugins/architecture-internals)。 ## 相关