> ## Documentation Index
> Fetch the complete documentation index at: https://openclaw.zhcndoc.com/llms.txt
> Use this file to discover all available pages before exploring further.

# 安全

<Warning>
  **个人助理信任模型。** 本指南假设每个网关都有一个受信任的操作员边界（单用户、个人助理模型）。
  OpenClaw 并不是供多个相互对抗的用户共享同一代理或网关时使用的敌对多租户安全边界。
  对于混合信任或对抗性用户的运行环境，应拆分信任边界：使用独立的网关和凭据，最好使用独立的操作系统用户或主机。
</Warning>

## 范围：个人助手安全模型

* 支持：每个网关对应一个用户/信任边界（最好每个边界对应一个 OS 用户/主机/VPS）。
* 不支持：由相互不信任或具有对抗性的用户共享同一个网关/代理。
* 面向对抗性用户的隔离需要独立的网关（理想情况下还需要独立的 OS 用户/主机）。
* 如果多个不受信任的用户可以向同一个启用工具的代理发送消息，那么他们共享该代理的委托工具权限。
* 如果有人可以修改 Gateway 主机状态/配置（`~/.openclaw`，包括 `openclaw.json`），则应将其视为受信任的操作员。
* 在一个 Gateway 内，经过身份验证的操作员访问是一种受信任的控制平面角色，而不是按用户划分的租户角色。
* `sessionKey`（会话 ID、标签）是路由选择器，不是授权令牌。

要托管多个用户或组织？请为每个租户运行一个隔离的 Gateway 单元，而不是共享一个 Gateway。参见 [多租户托管](/gateway/multi-tenant-hosting)。

在更改远程访问、DM 策略、反向代理或公开暴露之前，请先查看 [Gateway 暴露运行手册](/gateway/security/exposure-runbook)，作为预检/回滚检查清单。

## `openclaw security audit`

在任何配置更改后或在暴露网络入口之前运行此命令：

```bash theme={"theme":{"light":"min-light","dark":"min-dark"}}
openclaw security audit
openclaw security audit --deep    # 尝试进行一次实时 Gateway 探测
openclaw security audit --fix     # 应用安全的修复措施
openclaw security audit --json
```

`--fix` 的作用范围是有意限制的：它会将开放的群组策略切换为允许列表，收紧状态／配置／包含文件的权限（文件为 `600`，目录为 `700`），并在 Windows 上使用 ACL 重置，而不是 POSIX `chmod`。

### 审计会检查什么（高层概览）

* **入站访问** —— 私信／群组策略、允许列表：陌生人能否触发机器人？
* **工具影响范围** —— 高权限工具＋开放房间：提示注入是否可能转化为 shell／文件／网络操作？
* **执行文件系统偏移** —— 文件系统修改工具被拒绝，但 `exec`／`process` 仍可用且没有沙箱约束。
* **执行审批偏移** —— `security="full"`、`autoAllowSkills`、未启用 `strictInlineEval` 的解释器允许列表。单独的 `security="full"` 只是广泛的安全态势警告，并不能证明存在漏洞——对于受信任的个人助理设置，这是所选的默认配置；只有在威胁模型需要审批或允许列表防护时，才应收紧该设置。
* **网络暴露** —— Gateway 绑定／认证、Tailscale Serve／Funnel、弱或过短的认证令牌。
* **浏览器控制暴露** —— 远程节点、中继端口、远程 CDP 端点。
* **本地磁盘卫生** —— 权限、符号链接、配置包含、同步文件夹路径。
* **插件** —— 未通过显式允许列表加载。
* **策略偏移** —— 已配置 Docker 沙箱设置但沙箱模式处于关闭状态；看似生效但实际上只匹配精确命令 ID（例如 `system.run`），而不是负载中的 shell 文本的 `gateway.nodes.commands.deny` 条目；危险的 `gateway.nodes.commands.allow` 条目；全局 `tools.profile="minimal"` 被每个代理单独覆盖；在宽松策略下可访问的插件自有工具。
* **运行时预期偏移** —— 误以为隐式 exec 仍表示 `sandbox`，但此时 `tools.exec.host` 已默认为 `auto`；或者在沙箱模式关闭时设置 `tools.exec.host="sandbox"`。
* **模型卫生** —— 对已配置的旧版模型发出警告（软警告，不会强制阻止）。

每个发现都有结构化的 `checkId`（例如 `gateway.bind_no_auth`、`tools.exec.security_full_configured`）。前缀包括：`fs.*`（权限）、`gateway.*`（绑定／认证／Tailscale／控制 UI／可信代理）、`hooks.*`／`browser.*`／`sandbox.*`／`tools.exec.*`（各入口面的加固）、`plugins.*`／`skills.*`（供应链）、`security.exposure.*`（访问策略 × 工具影响范围）。完整目录（含严重性和自动修复支持）见：[安全审计检查](/gateway/security/audit-checks)。另见：[正式验证](/security/formal-verification)。

### 排查发现时的优先级顺序

1. 任何“开放”且启用了工具的情况：先锁定 DM／群组（配对／允许列表），然后再收紧工具策略／沙箱。
2. 公网网络暴露（LAN 绑定、Funnel、缺少认证）：立即修复。
3. 浏览器控制的远程暴露：按操作员访问来对待（仅限 tailnet，谨慎配对节点，不要公开暴露）。
4. 权限：state／config／凭据／认证不得对组或所有人可读。
5. 插件：只加载你明确信任的内容。
6. 模型选择：对于任何带工具的机器人，优先选择现代、经过指令强化的模型。

## 60 秒加固基线

```json5 theme={"theme":{"light":"min-light","dark":"min-dark"}}
{
  gateway: {
    mode: "local",
    bind: "loopback",
    auth: { mode: "token", token: "replace-with-long-random-token" },
  },
  session: {
    dmScope: "per-channel-peer",
  },
  tools: {
    profile: "messaging",
    deny: ["group:automation", "group:runtime", "group:fs", "sessions_spawn", "sessions_send"],
    fs: { workspaceOnly: true },
    exec: { security: "deny", ask: "always" },
    elevated: { enabled: false },
  },
  channels: {
    whatsapp: { dmPolicy: "pairing", groups: { "*": { requireMention: true } } },
  },
}
```

将 Gateway 保持为仅本地可用，隔离私聊，并默认禁用控制平面/运行时工具。之后可针对每个受信任的代理选择性重新启用工具。

适用于聊天驱动的代理回合的内置基线：无论配置如何，非所有者发送者都不能使用 `cron` 或 `gateway` 工具。

### 请求者范围的控制与提示上下文

`tools.toolsBySender`、发送者所有权以及仅限所有者使用的工具清单，都是根据当前回合的发起请求者进行评估的。它们不会对该模型提示中的其他内容进行身份验证或清理，包括引用文本、之前共享房间中的历史记录、转发内容、获取的内容、附件、工具结果或其他提示输入。因此，当其他人的内容被包含在所有者触发的回合上下文中时，该内容可能会影响该回合。

应将这些控制视为纵深防御措施，用于降低请求者的直接能力，而不是用于实现针对恶意多用户的隔离。使用 `contextVisibility` 过滤受支持的频道提供的上下文，限制工具并对代理实施沙箱；当参与者彼此具有敌意时，应使用独立的 Gateway，并且最好使用独立的操作系统用户或主机。

## 信任边界矩阵

用于对风险报告进行初步分流的简要模型：

| 边界或控制项                                                   | 含义                    | 常见误读                          |
| -------------------------------------------------------- | --------------------- | ----------------------------- |
| `gateway.auth`（token/password/trusted-proxy/device auth） | 对网关 API 的调用方进行身份验证    | “为了安全，每一帧都需要逐消息签名”            |
| `sessionKey`                                             | 用于上下文/会话选择的路由键        | “会话密钥就是用户认证边界”                |
| 提示词/内容防护栏                                                | 降低模型滥用风险              | “仅凭提示词注入就能证明认证绕过”             |
| `canvas.eval` / 浏览器 evaluate                             | 启用时属于有意开放给操作者的能力      | “任何 JS eval 原语在这种信任模型下都自动是漏洞” |
| 本地 TUI `!` shell                                         | 由操作者显式触发的本地执行         | “本地 shell 便捷命令就是远程注入”         |
| 节点配对和节点命令                                                | 已配对设备上的操作者级远程执行       | “远程设备控制默认应被视为不可信用户访问”         |
| `gateway.nodes.pairing.autoApproveCidrs`                 | 可选启用的受信任网络节点接入策略      | “默认禁用的允许列表就是自动配对漏洞”           |
| `gateway.nodes.pairing.sshVerify`                        | 通过操作者 SSH 进行密钥验证的节点接入 | “默认开启的自动批准就是自动配对漏洞”           |

## 非漏洞设计

<Accordion title="常见被关闭为无动作的发现">
  * 仅存在提示注入链、但没有策略、认证或沙箱绕过的情况。
  * 基于假设单一共享主机或配置存在恶意多租户运行的主张。
  * 正常运营者读路径访问（例如 `sessions.list` / `sessions.preview` / `chat.history`）在共享网关架构中被归类为 IDOR。
  * 仅限 localhost 的部署发现（例如仅在回环网关上缺少 HSTS）。
  * 针对本仓库中并不存在的入站路径的 Discord 入站 webhook 签名发现。
  * 将 Node 配对元数据视为 `system.run` 的隐藏第二层“按命令审批”机制；实际执行边界是网关的全局节点命令策略加上节点自身的执行审批。
  * 将 `gateway.nodes.pairing.sshVerify` 视为漏洞，因为它默认启用。它不会仅凭网络本地性或 SSH 可达性来批准：网关会通过 SSH 读取设备身份（BatchMode、严格主机密钥），且只有在与待处理请求的精确设备密钥匹配时才会批准，这要求连接所用的密钥对已经存在于操作员控制的主机上、并且位于操作员的账户下。探测范围限定在私有/CGNAT 源地址，沿用受信任 CIDR 的准入下限（仅限新鲜的无作用域 `role: node`），并且 `sshVerify: false` 会关闭该功能。
  * 将 `gateway.nodes.pairing.autoApproveCidrs` 本身视为漏洞。它默认禁用，需要显式的 CIDR/IP 条目，只适用于首次 `role: node` 配对且没有请求的作用域，并且绝不会自动批准 operator/browser/Control UI、WebChat、角色/作用域升级、元数据或公钥变更，也不会批准同主机回环受信任代理头路径（即使启用了回环受信任代理认证）。
  * 将 `sessionKey` 视为认证令牌而提出的“缺少每用户授权”发现。
</Accordion>

## Gateway 与节点信任

将 Gateway 和 node 视为一个具有不同角色的运维信任域：

* **Gateway**：控制平面和策略面（`gateway.auth`、工具策略、路由）。
* **Node**：与该 Gateway 配对的远程执行面（命令、设备操作、主机本地能力）。
* 经过 Gateway 认证的调用方在 Gateway 作用域内被信任；配对完成后，node 操作会被视为该 node 上的受信任运维操作。参见 [操作员作用域](/gateway/operator-scopes)。
* 使用共享的 gateway token/password 进行认证的直接回环后端客户端，可以在不提供用户设备身份的情况下发起内部控制平面 RPC。这不是远程或浏览器配对绕过——网络客户端、node 客户端、device-token 客户端以及显式设备身份仍然会经过配对和作用域升级强制校验。
* Exec 审批（allowlist + ask）是用于约束运维意图的护栏，而不是面向恶意多租户隔离的机制。它们会绑定精确的请求上下文，并尽力处理直接的本地文件操作数；但它们不会在语义上建模每一种运行时／解释器加载路径。要获得强边界，请使用沙箱和主机隔离。
* 默认信任单一运维者：在 `gateway`／`node` 上执行主机命令时允许无需审批提示（`security="full"`，`ask="off"`）。这是刻意的用户体验设计，本身并不是漏洞。

对于恶意用户隔离，请按操作系统用户／主机拆分信任边界，并运行独立的 gateways。

## 威胁模型

你的 AI 助手可以执行任意 shell 命令、读写文件、访问网络服务，并向任何人发送消息（如果被授予了频道访问权限）。与它交互的人可能会试图诱骗它做坏事、通过社会工程获取你的数据访问权限，或者探查基础设施细节。

这里的大多数失败并不是罕见的漏洞攻击——而是“有人给机器人发了消息，机器人照他们说的做了。”OpenClaw 的立场依次是：

1. **身份优先**——先决定谁可以与机器人对话（DM 配对 / 白名单 / 明确“开放”）。
2. **范围其次**——再决定机器人可以在哪里行动（群组白名单 + 提及门控、工具、沙箱、设备权限）。
3. **模型最后**——假设模型可能被操纵；设计时要让这种操纵的影响范围尽可能有限。

## DM 访问：配对、允许名单、开放、禁用

每个支持 DM 的通道都支持 `dmPolicy`（或 `*.dm.policy`），它会在消息被处理前对传入 DM 进行拦截：

| 策略          | 行为                                                                                       |
| ----------- | ---------------------------------------------------------------------------------------- |
| `pairing`   | 默认。未知发送者会获得一个配对码；在批准前机器人会忽略他们。配对码在 1 小时后过期；在创建新的请求之前，重复发送 DM 不会重新发送配对码。每个通道待处理请求上限为 3 个。 |
| `allowlist` | 未知发送者会被阻止，不进行配对握手。                                                                       |
| `open`      | 任何人都可以发送 DM（公开）。要求该通道允许名单包含 `"*"`（显式启用）。                                                 |
| `disabled`  | 完全忽略传入 DM。                                                                               |

```bash theme={"theme":{"light":"min-light","dark":"min-dark"}}
openclaw pairing list <channel>
openclaw pairing approve <channel> <code>
```

磁盘上的详细信息 + 文件： [配对](/channels/pairing)

将 `dmPolicy="open"` 和 `groupPolicy="open"` 视为最后手段设置；除非你完全信任房间中的每个成员，否则优先使用配对 + 允许名单。

### 允许名单（两层）

* **DM 允许名单** (`allowFrom` / `channels.discord.allowFrom` / `channels.slack.allowFrom`；旧版：`channels.discord.dm.allowFrom`、`channels.slack.dm.allowFrom`)：可以给机器人发送 DM 的人员。当 `dmPolicy="pairing"` 时，批准信息会写入 `~/.openclaw/credentials/<channel>-allowFrom.json`（默认账户）或 `<channel>-<accountId>-allowFrom.json`（非默认账户），并与配置中的允许名单合并。
* **群组允许名单**（特定通道）：机器人完全接受哪些群组/频道/服务器。
  * `channels.whatsapp.groups`、`channels.telegram.groups`、`channels.imessage.groups`：每个群组的默认设置，例如 `requireMention`；设置后也会作为群组允许名单（包含 `"*"` 以保持允许所有群组的行为）。使用 `agents.entries.*.groupChat.mentionPatterns` 自定义提及触发词（例如 `["@openclaw", "@mybot"]`），这样 `requireMention` 就会根据你自己的机器人名称进行限制。
  * `groupPolicy="allowlist"` + `groupAllowFrom`：限制谁可以在群组会话中触发机器人（WhatsApp/Telegram/Signal/iMessage/Microsoft Teams）。
  * `channels.discord.guilds` / `channels.slack.channels`：各界面的允许名单 + 提及默认设置。
  * 检查顺序：先检查 `groupPolicy`/群组允许名单，然后检查提及/回复激活。回复机器人消息（隐式提及）**不会**绕过 `groupAllowFrom`。

详情： [配置](/gateway/configuration) 和 [群组](/channels/groups)

### DM 会话隔离（多用户模式）

默认情况下，OpenClaw 会将所有 DM 路由到主会话，以实现跨设备连续性。如果有多人可以给机器人发 DM（开放 DM 或多人允许名单），请隔离 DM 会话：

```json5 theme={"theme":{"light":"min-light","dark":"min-dark"}}
{ session: { dmScope: "per-channel-peer" } }
```

`session.dmScope` 取值：

| 值                          | 范围                                 |
| -------------------------- | ---------------------------------- |
| `main`（配置默认值）              | 所有 DM 共享一个会话。                      |
| `per-channel-peer`         | 每个通道+发送者对获得一个隔离的 DM 上下文（安全 DM 模式）。 |
| `per-account-channel-peer` | 类似上面，但进一步按账户拆分（多账户通道）。             |
| `per-peer`                 | 每个发送者在同一类型的所有通道中共享一个会话。            |

本地 CLI 引导流程会保留显式设置的 `session.dmScope`，否则将其保持未设置状态，因此会应用 `"main"` 默认值：所有通道中的直接消息共享代理不断滚动的主会话（个人代理默认设置）。对于共享或多用户收件箱，请设置 `session.dmScope: "per-channel-peer"`；当检测到多用户 DM 流量时，`openclaw security audit` 会建议进行隔离。

这是一种消息上下文边界，不是主机管理员边界。如果用户彼此不信任且共享同一个 Gateway 主机/配置，应根据信任边界分别运行独立的网关。

如果同一个人在多个通道联系你，请使用 `session.identityLinks` 将这些 DM 会话合并为一个规范身份。另见 [会话管理](/concepts/session) 和 [配置](/gateway/configuration)。

## 上下文可见性 vs 触发授权

两个独立的概念：

* **触发授权**：谁可以触发代理（`dmPolicy`、`groupPolicy`、允许名单、提及门控）。
* **上下文可见性**：哪些补充上下文会传递给模型（回复正文、引用文本、线程历史、转发元数据）。

`contextVisibility` 控制第二项：

* `"all"`（默认）：补充上下文按接收时保持不变。
* `"allowlist"`：补充上下文会过滤为仅来自通过当前允许名单检查的发送者。
* `"allowlist_quote"`：类似 `allowlist`，但仍保留一条明确引用的回复。

可按频道或房间/对话分别设置 - 参见 [Groups](/channels/groups#context-visibility-and-allowlists)。那些只显示“模型可以看到来自未列入允许名单的发送者的引用/历史文本”的报告属于可加固项，可通过 `contextVisibility` 解决，而不是授权或沙箱绕过本身；一份具有安全影响的报告仍然需要展示信任边界被绕过。

## 提示注入

攻击者会精心构造一条消息，诱使模型执行不安全操作（“忽略你的指令”“转储你的文件系统”“打开这个链接并运行命令”）。提示注入**不能**仅靠系统提示词护栏来解决——那只是软性指导；真正的硬性约束来自工具策略、执行审批、沙箱，以及通道允许列表（而这些运维者出于设计仍可禁用）。

提示注入并不要求公开私信：即使只有你能给机器人发消息，任何它读取的**不受信任内容**（网页搜索／抓取结果、浏览器页面、电子邮件、文档、附件、粘贴的日志／代码）都可能携带对抗性指令。内容本身就是威胁面，而不只是发送者。

应视为不受信任的红旗：

* “阅读这个文件／URL，并严格按它说的做。”
* “忽略你的系统提示或安全规则。”
* “透露你的隐藏指令或工具输出。”
* “粘贴 \~/.openclaw 或你的日志的完整内容。”

实践中有帮助的方法：

* 保持传入私信处于锁定状态（配对／允许列表）；在群组中优先使用提及门控；避免在公共房间中使用始终在线的机器人。
* 默认将链接、附件和粘贴的指令视为恶意内容。
* 在沙箱中运行敏感工具执行；不要让秘密落入代理可访问的文件系统中。沙箱是可选启用的：如果沙箱模式关闭，隐式 `host=auto` 会解析到网关主机，而显式 `host=sandbox` 仍会失败并关闭（没有可用的沙箱运行时）。在配置中设置 `host=gateway` 可使该行为显式化。
* 将高风险工具（`exec`、`browser`、`web_fetch`、`web_search`）限制给受信任代理或显式允许列表。
* 如果你允许列出解释器（`python`、`node`、`ruby`、`perl`、`php`、`lua`、`osascript`），请启用 `tools.exec.strictInlineEval`，这样内联求值形式（`-c`、`-e` 以及类似形式）仍需要显式审批。在允许列表模式下，任何 heredoc 片段（`<<`）无论引号如何都始终需要审阅者或显式批准——允许列表中的命令不能借助 heredoc 正文绕过允许列表审查。
* 通过使用只读或禁用工具的**阅读器代理**来总结不受信任内容，然后将摘要传递给你的主代理，以降低爆炸半径。
* 对于 Gmail 钩子，内置的每条消息会话会隔离会话上下文，但不会移除目标代理的工具或工作区权限。将不受信任的邮件路由到专用阅读器代理，对其应用[按代理的沙箱和工具限制](/tools/multi-agent-sandbox-tools)，并使用 [`tools.agentToAgent`](/gateway/config-tools#toolsagenttoagent) 约束传递给主代理的任何交接。参见 [Gmail 集成](/gateway/configuration-reference#gmail-integration)。
* 对于启用工具的代理，除非确有需要，否则关闭 `web_search` ／ `web_fetch` ／ `browser`。
* 对于 OpenResponses 的 URL 输入（`input_file` ／ `input_image`），设置严格的 `gateway.http.endpoints.responses.files.urlAllowlist` ／ `images.urlAllowlist` 并保持 `maxUrlParts` 较低（空允许列表视为未设置）。使用 `files.allowUrl: false` ／ `images.allowUrl: false` 可完全禁用 URL 获取。
* 将秘密信息排除在提示之外；改为通过网关主机上的环境变量／配置传递。

**模型选择很重要。** 提示注入抗性在不同模型层级之间并不一致——在对抗性提示下，较小／较便宜的模型更容易被滥用工具和劫持指令。

<Warning>
  对于启用工具的代理，或会读取不受信任内容的代理，较旧／较小模型上的提示注入风险通常过高。不要在弱模型层级上运行这些工作负载。
</Warning>

* 对于任何能够运行工具或接触文件／网络的机器人，使用最新一代、最高级别的模型。
* 不要为启用工具的代理或不受信任的收件箱使用更旧／更弱／更小的层级。
* 如果必须使用更小的模型，请缩小爆炸半径：只读工具、强沙箱、最小文件系统访问、严格允许列表。为所有会话启用沙箱，并在输入没有严格控制时禁用 `web_search` ／ `web_fetch` ／ `browser`。
* 对于仅聊天、输入可信且无工具的个人助理，较小的模型通常足够。

### 外部内容与不受信任输入包装

即使 Gateway 在本地解码，OpenResponses 的 `input_file` 文本仍会作为不受信任的外部内容注入——该块带有 `<<<EXTERNAL_UNTRUSTED_CONTENT ...>>>` 边界标记以及 `Source: External` 元数据（此路径省略了其他地方使用的较长 `SECURITY NOTICE:` 横幅）。当媒体理解在将文本附加到媒体提示之前从附件文档中提取文本时，同样的基于标记的包装也适用。

OpenClaw 还会在这些包装后的外部内容和元数据到达模型之前，剥离常见的自托管 LLM 聊天模板特殊 token 字面量（Qwen／ChatML、Llama、Gemma、Mistral、Phi、GPT-OSS 的角色／轮次 token）。自托管的 OpenAI 兼容后端（vLLM、SGLang、TGI、LM Studio、自定义 Hugging Face 分词器栈）有时会把诸如 `<|im_start|>` 或 `<|start_header_id|>` 之类的字面字符串，在用户内容中当作结构化聊天模板 token 进行分词；如果没有这种净化，从抓取页面、邮件正文或文件内容工具输出中的不受信任文本，就可能伪造出合成的 `assistant`／`system` 角色边界。净化发生在外部内容包装层，因此对所有抓取／读取工具和传入通道内容都统一生效。托管提供商（OpenAI、Anthropic）已经在请求侧应用了各自的净化；请保持外部内容包装启用，并在可用时优先选择会拆分／转义特殊 token 的后端设置。

发往外部的模型响应还有单独的净化器，会在最终通道交付边界从用户可见回复中剥离泄露的 `<tool_call>`、`<function_calls>`、`<system-reminder>`、`<previous_response>` 以及类似的内部脚手架。

这并不能替代 `dmPolicy`、允许列表、执行审批、沙箱或 `contextVisibility`——它只关闭一种特定的分词器层绕过方式。

### 绕过标志（生产环境保持关闭）

* `hooks.mappings[].allowUnsafeExternalContent`
* `hooks.gmail.allowUnsafeExternalContent`
* Cron 载荷字段 `allowUnsafeExternalContent`

仅在范围极小的调试场景下临时启用；如果启用，请隔离该代理（沙箱 + 最少工具 + 专用会话命名空间）。

即使投递来自你控制的系统，hook 载荷仍然是未受信任内容（邮件／文档／网页内容都可能携带提示注入）。较弱的模型层级会增加这种风险——对于由 hook 驱动的自动化，优先使用强大的现代模型层级，并保持严格的工具策略（`tools.profile: "messaging"` 或更严格），并尽可能启用沙箱。

### 组内推理与详细输出

`/reasoning`、`/verbose` 和 `/trace` 可能会暴露不适合公开频道的内部推理、工具输出或插件诊断信息——其中可能包含工具参数、URL、插件诊断以及模型所见数据。请在公共房间中将它们禁用；仅在受信任的私信或严格受控的房间中启用。

## 命令授权

Slash commands 和 directives 仅对已授权的发送者生效。配置明确的、按 provider 划分的 `commands.allowFrom` 列表，或让命令授权遵循 channel allowlists 和配对状态。channel allowlists 所引用的 access-group 条目会自动解析；无需启用任何切换项。如果某个 channel allowlist 为空或包含 `"*"`，则该 channel 的命令实际上处于开放状态。请参阅 [Access groups](/channels/access-groups) 和 [Slash commands](/tools/slash-commands)。

`/exec` 仅是面向授权操作员的会话内便捷功能——它不会写入配置，也不会影响其他会话。

## 控制平面工具

仍有两个内置工具对控制平面敏感：

* `gateway` 使用 `config.schema.lookup` / `config.get` 读取配置。它无法写入配置、更新 OpenClaw 或重启 Gateway。
* `cron` 创建计划任务，即使原始聊天/任务结束后，这些任务仍会继续运行。

`gateway` 工具仍仅限所有者使用，因为配置读取可能暴露机密信息和主机拓扑。Agent 通过 `openclaw` 委托工具请求持久化配置或生命周期变更；OpenClaw 会将这些请求映射为类型化操作，并在应用之前要求人工批准。请参阅 [OpenClaw 设置 Agent](/cli/openclaw#operations-and-approval)。

对于任何处理不受信任内容的 agent/surface，默认拒绝这些：

```json5 theme={"theme":{"light":"min-light","dark":"min-dark"}}
{
  tools: {
    deny: ["gateway", "cron", "sessions_spawn", "sessions_send"],
  },
}
```

`commands.restart=false` 会禁用 `/restart` 和外部 `SIGUSR1` 重启请求。`gateway` agent 工具没有重启操作。

## 节点执行（`system.run`）

如果一个 macOS 节点已配对，Gateway 可以在其上调用 `system.run`——这就是在该 Mac 上的远程代码执行。

* 需要节点配对（批准 + 令牌）。配对会建立节点身份/信任并签发令牌；它不是逐条命令的批准界面。
* Gateway 通过 `gateway.nodes.commands.allow` / `gateway.nodes.commands.deny` 应用粗粒度的全局节点命令策略。拒绝列表仅匹配精确的节点命令名称（例如 `system.run`），不会匹配命令负载中的 shell 文本——如果重新连接的节点声明了不同的命令列表，只要 Gateway 全局策略和节点自身的执行批准仍然强制执行边界，这本身并不是漏洞。
* 每个节点的 `system.run` 策略由节点自身的执行批准文件（`exec.approvals.node.*`）决定，可在 Mac 上通过“设置 -> 执行批准”（安全性 + 询问 + 允许列表）进行控制；它可以比 Gateway 的全局命令 ID 策略更严格，也可以更宽松。
* 运行在 `security="full"` 且 `ask="off"` 配置下的节点遵循默认的受信任操作者模型——这是预期行为，而不是错误，除非你的部署需要更严格的安全策略。
* 批准模式会绑定精确的请求上下文，并在可能的情况下绑定一个具体的本地脚本/文件操作数。如果 OpenClaw 无法为解释器/运行时命令准确识别出唯一一个直接的本地文件，则会拒绝基于批准的执行，而不是声称能够实现完整的语义覆盖。
* 对于 `host=node`，基于批准的运行还会存储规范化的已准备 `systemRunPlan`；之后获批准的转发会复用该已存储的计划，并且 Gateway 会拒绝调用方在批准请求创建后对命令、cwd 或会话上下文进行的编辑。
* 如需完全禁用远程执行：将安全策略设置为 `deny`，并移除该 Mac 的节点配对。

## 动态技能（watcher / 远程节点）

OpenClaw 可以在会话进行过程中刷新技能列表：当 `SKILL.md` 发生变化时，skills watcher 会在下一次代理回合更新快照；连接 macOS 节点可以使仅限 macOS 的技能变为可用（基于二进制探测）。请将技能文件夹视为受信任的代码，并限制谁可以修改它们。

## 插件

插件与 Gateway 在同一进程中运行——请将它们视为受信任的代码。

* 仅从你信任的来源安装；优先使用明确的 `plugins.allow` 白名单；启用前检查插件配置；插件变更后重启 Gateway。
* 安装/更新插件会运行可执行代码：
  * 安装路径是活动插件安装根目录下的每个插件目录。
  * ClawHub 软件包以及 OpenClaw 内置/官方目录是受信任的来源。新的任意 npm、`npm-pack:`、git、本地路径/归档文件或市场来源在安装前会发出警告；非交互式安装在你审查并信任该来源后，需要使用 `--force`。`--force` 会确认来源并允许覆盖；它不会绕过 `security.installPolicy` 或其余安装安全检查。更新会复用已选择的来源。
  * OpenClaw 不会在安装/更新期间执行内置的本地危险代码拦截。请使用 `security.installPolicy` 进行由操作员负责的本地允许/阻止决策，并使用 `openclaw security audit --deep` 执行诊断扫描。
  * npm 和 git 插件安装仅在明确的安装/更新流程中运行包管理器依赖收敛。本地路径和归档文件会被视为自包含软件包；OpenClaw 会复制/引用它们，而不会运行 `npm install`。
  * 优先使用固定的精确版本（`@scope/pkg@1.2.3`），并在启用前检查解压后的代码。
  * `--dangerously-force-unsafe-install` 已弃用，不再改变安装/更新行为。
  * `security.installPolicy` 允许操作员运行受信任的本地命令，为技能和插件安装做出针对主机的允许/阻止决策。它会在源材料准备完成后、安装继续之前运行，同样适用于 ClawHub 技能，且不会被已弃用的不安全标志绕过。

详情： [插件](/tools/plugin)。

## 沙箱

专门文档：[沙箱](/gateway/sandboxing)

两种互补的方法：

* **Docker 中的完整网关**（容器边界）：[Docker](/install/docker)
* **工具沙箱**（`agents.defaults.sandbox`；主机网关 + 沙箱隔离工具；内置 Docker 和 Podman 后端）：[沙箱](/gateway/sandboxing)

<Note>
  为防止跨代理访问，请将 `agents.defaults.sandbox.scope` 保持为 `"agent"`（默认值），或使用 `"session"` 以实现更严格的按会话隔离。`scope: "shared"` 会使用单个容器或工作区。
</Note>

沙箱内的代理工作区访问（`agents.defaults.sandbox.workspaceAccess`）：

* `"none"`（默认）：工具会看到位于 `~/.openclaw/sandboxes` 下的沙箱工作区；代理工作区不可访问。
* `"ro"`：将代理工作区以只读方式挂载到 `/agent`（禁用 `write`/`edit`/`apply_patch`）。
* `"rw"`：将代理工作区以读写方式挂载到 `/workspace`。

额外的 `sandbox.docker.binds` 会根据规范化、标准化后的源路径进行校验。被阻止路径的拒绝名单涵盖 `/etc`、`/private/etc`、`/proc`、`/sys`、`/dev`、`/root`、`/boot`，以及通常包含 Docker socket 或指向其别名的目录（`/run`、`/var/run`，以及其下的 `docker.sock`），另外还包括 HOME 凭据子路径（`.aws`、`.cargo`、`.config`、`.docker`、`.gnupg`、`.netrc`、`.npm`、`.ssh`）。父级符号链接技巧和规范化的 home 别名会通过已有祖先解析并重新检查，因此如果它们最终解析到被阻止的根目录，仍会以封闭方式失败。

<Warning>
  `tools.elevated` 是全局基线逃生口，可在沙箱外运行 exec。默认情况下，有效主机是 `gateway`；当 exec 目标配置为 `node` 时，则为 `node`。请严格限制 `tools.elevated.allowFrom`，不要为陌生人启用它。还可通过 `agents.entries.*.tools.elevated` 对每个代理进行进一步限制。请参阅[提升模式](/tools/elevated)。
</Warning>

### 子代理委派防护

如果你允许会话工具，请将委派的子代理运行视为另一项边界决策：

* 除非代理确实需要委派，否则拒绝 `sessions_spawn`。
* 将 `agents.defaults.subagents.allowAgents` 以及任何针对代理的 `agents.entries.*.subagents.allowAgents` 覆盖项限制为已知安全的目标代理。
* 对于必须保持沙箱隔离的工作流，请使用 `sandbox: "require"` 调用 `sessions_spawn`（默认值为 `"inherit"`）；当目标子运行时未处于沙箱中时，`"require"` 会快速失败。

### 只读模式

通过组合 `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/multi-agent-sandbox-tools)。

常见模式：个人代理（完全访问，无沙箱）、家庭/工作代理（沙箱化 + 只读工具）、公共代理（沙箱化 + 无文件系统/外壳工具）。

### 完全访问（无沙箱）

```json5 theme={"theme":{"light":"min-light","dark":"min-dark"}}
{
  agents: {
    entries: {
      personal: {
        default: true,
        workspace: "~/.openclaw/workspace-personal",
        sandbox: { mode: "off" },
      },
    },
  },
}
```

### 只读工具 + 只读工作区

```json5 theme={"theme":{"light":"min-light","dark":"min-dark"}}
{
  agents: {
    entries: {
      family: {
        default: true,
        workspace: "~/.openclaw/workspace-family",
        sandbox: { mode: "all", scope: "agent", workspaceAccess: "ro" },
        tools: {
          allow: ["read"],
          deny: ["write", "edit", "apply_patch", "exec", "process", "browser"],
        },
      },
    },
  },
}
```

### 无文件系统/外壳访问（允许提供方消息传递）

```json5 theme={"theme":{"light":"min-light","dark":"min-dark"}}
{
  // Session tools can reveal transcript data. Default scope is current + spawned;
  // reads also include same-agent groups watched through ambient group awareness.
  // Use visibility: "self" to exclude those watched sessions.
  tools: { sessions: { visibility: "tree" } }, // self | tree | agent | all
  agents: {
    entries: {
      public: {
        default: true,
        workspace: "~/.openclaw/workspace-public",
        sandbox: { mode: "all", scope: "agent", workspaceAccess: "none" },
        tools: {
          allow: [
            "sessions_list",
            "sessions_history",
            "sessions_send",
            "sessions_spawn",
            "session_status",
            "discord",
            "slack",
            "telegram",
            "whatsapp",
          ],
          deny: [
            "apply_patch",
            "browser",
            "canvas",
            "cron",
            "edit",
            "exec",
            "gateway",
            "image",
            "nodes",
            "process",
            "read",
            "write",
          ],
        },
      },
    },
  },
}
```

## 浏览器控制风险

启用浏览器控制会让模型获得一个真实浏览器。如果该配置文件已经有登录会话，模型就可以访问那些账户和数据——请将浏览器配置文件视为敏感状态。

* 优先为 agent 使用专用配置文件（默认的 `openclaw` 配置文件）；避免使用你个人日常使用的配置文件。
* 除非你信任沙箱 agent，否则请保持对其禁用主机浏览器控制。
* 独立的 loopback 浏览器控制 API 仅支持 shared-secret 认证（Gateway token bearer 认证或 Gateway password）——它不会使用 trusted-proxy 或 Tailscale Serve 身份标头。
* 将浏览器下载内容视为不受信任的输入；优先使用隔离的下载目录。
* 如果可能，请在 agent 配置文件中禁用浏览器同步和密码管理器。
* 对于远程 Gateway，“浏览器控制”等同于对该配置文件能够访问的任何内容拥有“操作者访问权限”。
* 保持 Gateway 和 node 主机仅限 tailnet 访问；避免将浏览器控制端口暴露给 LAN 或公共互联网。
* 不需要时禁用浏览器代理路由（`gateway.nodes.browser.mode="off"`）。
* Chrome MCP existing-session 模式并不“更安全”——它可以代表你操作该主机上的 Chrome 配置文件能够访问的任何内容。
* Browser Relay Authentication v2 永远不会发送持久化的扩展 relay key。扩展和外部 CDP 客户端会在返回短期、一次性、与连接绑定的 HMAC proof 之前，验证带签名的服务器 challenge。Proof 会绑定 protocol version、role、transport、method、resource、flow、profile 和 relay instance；在同一或其他 socket 上重放都会失败。
* `browser.extensionRelay.allowLegacyAuth` 默认设为 `true`，用于一个迁移窗口期。这会临时接受旧版 Bearer、Basic 和 token-subprotocol relay 客户端。更新所有 relay 客户端后，将其设为 `false`。V2 客户端在 proof 失败或收到不支持的响应后永远不会降级。
* Chrome 扩展配对会将其访问模式存储在扩展自有的 Chrome 存储中，而不是 Gateway 配置中。**All tabs** 会暴露该 Chrome 配置文件中所有符合条件的普通标签页，但会排除已暂停会话的标签页；**Selected tabs** 使用 OpenClaw 标签页组作为其 ACL。现有配对会迁移到 **Selected tabs**，而新的个人浏览器配对推荐使用 **All tabs**。无论哪种模式，Incognito 和 Chrome 内部页面都会被排除。
* 自动 Chrome 扩展设置会使用 origin-locked native messaging manifest，该 manifest 从 Chrome 配置文件元数据中发现的精确解压扩展路径获取。一次性 host 仅接受带版本的请求和新鲜 nonce，将输入限制为 4 KiB，验证 Chrome 提供的 origin，并且只返回本地拥有的配对信息。它永远不会传输远程 Gateway key。
* Native-host manifests、launchers 和状态输出不包含 pairing key。OpenClaw 会拒绝符号链接、不安全的所有权或模式、通配符 origin，以及使用相同 host name 的外部注册。Windows 在支持可执行 native-host 路径之前，会使用手动配对回退方案。
* 在浏览器所在机器上运行 **node host**，并在 Gateway 与浏览器不在同一台机器时，让 Gateway 代理浏览器操作（参见[浏览器工具](/tools/browser)）；将 node 配对视同管理员访问权限，保持 Gateway 和 node host 位于同一 tailnet，并避免通过 LAN、公共互联网或 Tailscale Funnel 暴露 relay/control 端口。

### 浏览器 SSRF 策略（默认严格）

除非你明确选择允许，否则私有/内部目标会保持阻止。

* 默认：未设置 `browser.ssrfPolicy.dangerouslyAllowPrivateNetwork`，因此私有/内部/特殊用途目标会保持阻止。旧版别名 `allowPrivateNetwork` 仍然受支持。
* 选择性启用：将 `dangerouslyAllowPrivateNetwork: true` 设为允许这些目标。
* 在严格模式下，对类似 `*.example.com` 的模式以及精确的主机例外使用支持通配符的 `allowedHostnames` 条目，其中包括 `localhost` 等原本会被阻止的名称。
* 直接导航请求会经过预检检查。在操作期间及有界的操作后宽限期内，受保护的 Playwright 交互（点击、坐标点击、悬停、拖拽、滚动、选择、按键、输入、表单填充和 evaluate）会在 HTTP 请求字节发出之前拦截策略拒绝的顶层和子框架文档加载，然后以尽力而为的方式再次检查最终的 `http(s)` URL。
* 在每次启动全新的托管 Chrome 之前，OpenClaw 会尽力禁用网络预测，抑制 Chromium 针对这些被拒绝加载的已观测推测性预连接。这是纵深防御，而不是策略边界：在控制服务重启后复用的浏览器以及其他浏览器后端可能不会共享这些强化措施。页面路由仍然是请求级拦截，而不是网络防火墙：重定向跳转、弹出窗口的首次请求、Service Worker 流量、有界防护窗口结束后运行的页面代码，以及某些后台/子资源路径都可能绕过它。最终 URL 检查仍然属于检测/隔离防御；要实现完整阻止，需要所有者一侧的出口隔离或实施策略的代理。

```json5 theme={"theme":{"light":"min-light","dark":"min-dark"}}
{
  browser: {
    ssrfPolicy: {
      dangerouslyAllowPrivateNetwork: false,
      allowedHostnames: ["*.example.com", "example.com", "localhost"],
    },
  },
}
```

## 网络暴露

### 绑定、端口、防火墙

Gateway 在一个端口上复用 WebSocket + HTTP（默认 `18789`；配置/标志/环境变量：`gateway.port`、`--port`、`OPENCLAW_GATEWAY_PORT`）。该 HTTP 入口包含 Control UI（SPA 资源，默认基础路径 `/`）以及画布主机（`/__openclaw__/canvas` 和 `/__openclaw__/a2ui` - 任意 HTML/JS；在普通浏览器中加载时应将其视为不受信任内容；不要将其暴露给不受信任的网络/用户，也不要与具有特权的 Web 入口共享同一来源）。

`gateway.bind` 控制 Gateway 监听的位置：

* `"loopback"`（默认）：只有本地客户端可以连接。
* `"lan"`、`"tailnet"`、`"custom"`：会扩大攻击面。仅在启用 gateway 身份验证（共享令牌/密码，或正确配置的受信任代理）并配合真实防火墙时使用。

经验法则：优先使用 Tailscale Serve，而不是 LAN 绑定（Serve 会让 Gateway 保持在 loopback 上，由 Tailscale 处理访问）；如果必须绑定到 LAN，请将端口通过防火墙严格限制到源 IP 白名单，而不是广泛地做端口转发；绝不要在 `0.0.0.0` 上以未认证方式暴露 Gateway。

### 使用 UFW 进行 Docker 端口发布

已发布的容器端口（`-p HOST:CONTAINER` 或 Compose `ports:`）会通过 Docker 的转发链路路由，而不仅仅是主机的 `INPUT` 规则。应在 `DOCKER-USER` 中强制执行规则（该链在 Docker 自身的 accept 规则之前被评估）；大多数现代发行版使用 `iptables-nft` 前端，它仍会将这些规则应用到 nftables 后端。

```bash theme={"theme":{"light":"min-light","dark":"min-dark"}}
# /etc/ufw/after.rules（作为独立的 *filter 段追加）
*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*` 等），而且名称不匹配可能会悄无声息地跳过你的拒绝规则。

```bash theme={"theme":{"light":"min-light","dark":"min-dark"}}
ufw reload
iptables -S DOCKER-USER
ip6tables -S DOCKER-USER
nmap -sT -p 1-65535 <public-ip> --open
```

期望的外部端口应该只包括你有意暴露的端口（对于大多数配置：SSH + 反向代理端口）。

### mDNS/Bonjour 发现

当启用捆绑的 `bonjour` 插件时，Gateway 会通过 mDNS（`_openclaw-gw._tcp`，端口 5353）广播存在信息，以便进行本地设备发现。完整模式会包含暴露运行细节的 TXT 记录：`cliPath`（文件系统路径，会泄露用户名和安装位置）、`sshPort`（宣告 SSH 可用性）、`displayName`/`lanHost`（主机名信息）。广播基础设施细节会让局域网侦察更容易。

* 除非确实需要局域网发现，否则请保持 Bonjour 禁用——它会在 macOS 主机上自动启动，而在其他平台上则需要显式启用；直接使用 Gateway URL、Tailnet、SSH 或广域 DNS-SD 可以避免本地组播。

* **最小模式**（启用 Bonjour 时的默认模式，建议用于暴露在外的 gateway）会省略敏感字段：

  ```json5 theme={"theme":{"light":"min-light","dark":"min-dark"}}
  { discovery: { mdns: { mode: "minimal" } } }
  ```

* **关闭** 会在保留插件启用的同时抑制本地发现：

  ```json5 theme={"theme":{"light":"min-light","dark":"min-dark"}}
  { discovery: { mdns: { mode: "off" } } }
  ```

* **完整模式**（显式启用）会包含 `cliPath` + `sshPort`：

  ```json5 theme={"theme":{"light":"min-light","dark":"min-dark"}}
  { discovery: { mdns: { mode: "full" } } }
  ```

* 或设置 `OPENCLAW_DISABLE_BONJOUR=1`，无需修改配置即可禁用 mDNS。

在最小模式下，Gateway 会广播 `role`、`gatewayPort`、`transport`，但不包含 `cliPath`/`sshPort`；需要 CLI 路径的应用可以改为通过已认证的 WebSocket 连接获取。

### Gateway WebSocket 认证

默认情况下需要 Gateway 认证——如果没有配置有效的认证路径，Gateway 会拒绝 WebSocket 连接（失败关闭，fail-closed）。首次配置时默认会生成一个令牌（即使是回环地址也一样），因此本地客户端必须进行身份验证。

```json5 theme={"theme":{"light":"min-light","dark":"min-dark"}}
{ gateway: { auth: { mode: "token", token: "your-token" } } }
```

`openclaw doctor --generate-gateway-token` 可以为你生成一个。

<Note>
  `gateway.remote.token` 和 `gateway.remote.password` 是客户端凭据来源——它们本身不会保护本地 WS 访问。只有当 `gateway.auth.*` 未设置时，本地调用路径才会将 `gateway.remote.*` 作为后备方案。如果通过 SecretRef 显式配置了 `gateway.auth.token` 或 `gateway.auth.password`，但解析失败，则会失败关闭（不会被远程后备方案掩盖）。
</Note>

在使用 `wss://` 时，请使用 `gateway.remote.tlsFingerprint` 固定远程 TLS。明文 `ws://` 适用于回环地址、私有 IP 字面量、`.local` 以及 Tailnet `*.ts.net` 网关 URL；对于其他受信任的私有 DNS 名称，请在客户端进程中设置 `OPENCLAW_ALLOW_INSECURE_PRIVATE_WS=1` 作为紧急开关（仅限进程环境变量，不是 `openclaw.json` 键）。移动配对和 Android 手动/扫描网关路径更为严格：明文仅允许回环地址，而私有局域网、链路本地、`.local` 和无点主机名必须使用 TLS，除非你明确启用受信任的私有网络明文路径。

设备配对在直接本地回环连接时会自动批准（此外，对于受信任的共享密钥辅助流程，还包括一个狭窄的后端/容器本地自连接路径）；Tailnet 和 LAN 连接，包括同主机连接到 tailnet 地址，都被视为远程连接，仍然需要批准。解析后的 `tailnet` 地址或 `custom` 地址（除 `127.0.0.1` 或 `0.0.0.0` 外）会额外添加一个 `127.0.0.1` 监听器；只有连接到该本地监听器时才会获得回环语义。回环请求上的转发头证据会使其不再符合回环本地性；元数据升级的自动批准范围也很窄。参见 [Gateway 配对](/gateway/pairing)。

认证模式：

* `"token"`：共享持有者令牌（推荐用于大多数配置）。
* `"password"`：建议通过 `OPENCLAW_GATEWAY_PASSWORD` 设置。
* `"trusted-proxy"`：信任具备身份感知能力的反向代理来认证用户，并通过头部传递身份。参见 [受信任代理认证](/gateway/trusted-proxy-auth)。

轮换检查清单（token/password）：生成/设置新的密钥（`gateway.auth.token` 或 `OPENCLAW_GATEWAY_PASSWORD`）；重启 Gateway（如果由 macOS 应用托管 Gateway，也需要重启该应用）；更新远程客户端（`gateway.remote.token`/`.password`）；确认旧凭据已不再有效。

### Tailscale Serve 身份头

当 `gateway.auth.allowTailscale` 为 `true`（Serve 默认值）时，OpenClaw 会接受用于 Control UI/WebSocket 身份验证的 Tailscale Serve 身份头 `tailscale-user-login`。它通过本地 Tailscale 守护进程（`tailscale whois`）解析 `x-forwarded-for` 地址并将其与该头进行匹配来验证身份——这仅会针对由 Tailscale 注入、并携带 `x-forwarded-for`、`x-forwarded-proto` 和 `x-forwarded-host` 的回环请求触发。对于这个异步检查，在限流器记录失败之前，同一 `{scope, ip}` 的失败尝试会被串行化，因此来自同一个 Serve 客户端的并发错误重试可能会立即锁定第二次尝试。

HTTP API 端点（`/v1/*`、`/tools/invoke`、`/api/channels/*`）不使用 Tailscale 身份头认证——它们遵循网关配置的 HTTP 认证模式。

网关的 HTTP bearer 认证本质上是“要么全开，要么全关”的运维访问。能够调用 `/v1/chat/completions`、`/v1/responses`、诸如 `/api/v1/admin/rpc` 之类的插件路由，或 `/api/channels/*` 的凭据，都是该网关的完全访问运维密钥：共享密钥 bearer 认证会恢复默认的全部运维作用域（`operator.admin`、`operator.approvals`、`operator.pairing`、`operator.read`、`operator.talk.secrets`、`operator.write`）以及用于 agent 回合的 owner 语义，而更窄的 `x-openclaw-scopes` 值不会缩小该共享密钥路径的权限。按请求的作用域语义仅在请求来自具有身份的模式（可信代理认证）或显式无认证的私有入口时适用；在这些模式下，如果省略 `x-openclaw-scopes`，则回退到正常的运维默认作用域集，而像 `x-openclaw-model` 这样的 owner 级头部在作用域被缩窄时需要 `operator.admin`。`/tools/invoke` 和 HTTP 会话历史端点遵循相同的共享密钥规则。不要将这些凭据与不受信任的调用方共享；最好针对不同的信任边界使用不同的网关。

无令牌的 Serve 认证默认信任网关主机本身——它不能防御同主机上的恶意进程。如果不受信任的本地代码可能在网关主机上运行，请禁用 `allowTailscale` 并要求显式共享密钥认证（`token` 或 `password`）。

不要从你自己的反向代理转发这些头。如果你在网关前终止 TLS 或进行代理，请禁用 `allowTailscale`，并改用共享密钥认证或[可信代理认证](/gateway/trusted-proxy-auth)。

参见 [Tailscale](/gateway/tailscale) 和[Web 概览](/web)。

### 反向代理配置

在 nginx/Caddy/Traefik 等后面使用时，设置 `gateway.trustedProxies` 以正确处理转发客户端 IP。当 Gateway 检测到来自 **不在** `trustedProxies` 中的地址的代理头时，它不会将该连接视为本地连接；如果禁用了 gateway auth，则该连接会被拒绝。这可以防止经由代理的连接伪装成来自 localhost 并获得自动信任。

`trustedProxies` 也会影响 `gateway.auth.mode: "trusted-proxy"`，这是一个更严格的模式：默认情况下，它会对来源为 loopback 的代理进行“失败即关闭”。同主机上的 loopback 反向代理可以使用 `trustedProxies` 进行本地客户端检测和转发 IP 处理，但只有在 `gateway.auth.trustedProxy.allowLoopback = true` 时才能满足 `trusted-proxy` 认证模式；否则请使用 token/password 认证。

```yaml theme={"theme":{"light":"min-light","dark":"min-dark"}}
gateway:
  trustedProxies:
    - "10.0.0.1" # 反向代理 IP
  allowRealIpFallback: false # 默认 false；仅当你的代理无法提供 X-Forwarded-For 时才启用
  auth:
    mode: password
    password: ${OPENCLAW_GATEWAY_PASSWORD}
```

当设置了 `trustedProxies` 时，Gateway 会使用 `X-Forwarded-For` 来确定客户端 IP；除非显式设置 `gateway.allowRealIpFallback: true`，否则会忽略 `X-Real-IP`。请确保你的代理会**覆盖** `X-Forwarded-For`/`X-Real-IP`，而不是在其后追加：

```nginx theme={"theme":{"light":"min-light","dark":"min-dark"}}
# 正确
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header X-Real-IP $remote_addr;

# 错误：保留/追加了不受信任的客户端提供的值
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
```

受信任的代理头不会自动使节点设备配对变为受信任 - `gateway.nodes.pairing.autoApproveCidrs` 是一个单独的、默认禁用的运维策略，而且即使启用了 loopback 来源的 trusted-proxy 认证，来自 loopback-source 的 trusted-proxy 头路径仍会被排除在节点自动批准之外（因为本地调用方可以伪造这些头）。

### HSTS 和 origin 注意事项

* OpenClaw 的网关首先面向本地/回环地址。如果在反向代理处终止 TLS，请在那里设置 HSTS。
* 如果网关本身终止 HTTPS，`gateway.http.securityHeaders.strictTransportSecurity` 会让 OpenClaw 响应携带 HSTS 标头。
* 非回环的控制 UI 部署默认需要配置 `gateway.controlUi.allowedOrigins`；`allowedOrigins: ["*"]` 是明确的全允许策略，并非强化的默认设置——除非是在严格控制的本地测试环境中，否则应避免使用。
* 来自回环地址的身份验证失败永远不会触发锁定，因此本地 CLI 在凭据检查前不会被拒绝。错误凭据仍会被记录，并逐步增加延迟（延迟有上限，每个密钥共用一个计时器）；成功身份验证会重置失败记录。这提高了来自单一回环源的重复猜测成本；但这并不能防御已经能够打开大量并行回环连接的攻击者，因为凭据会在延迟失败响应之前进行比较。回环可达性本身就是一个信任边界——请参阅 [节点配对](/gateway/pairing#silent-local-pairing)。
* 即使启用了常规回环豁免，浏览器来源的回环身份验证失败仍会受到速率限制，但锁定密钥的作用域是规范化后的 `Origin` 值，而不是共用的 localhost 令牌桶。
* `gateway.controlUi.dangerouslyAllowHostHeaderOriginFallback=true` 会启用 Host 标头来源回退模式；应将其视为由操作员明确选择的危险策略。
* 应将 DNS 重绑定和代理 Host 标头行为视为部署强化问题；请严格限制 `trustedProxies`，并避免将网关直接暴露到公共互联网。
* 详细的部署指南：[受信任代理身份验证](/gateway/trusted-proxy-auth#tls-termination-and-hsts)。

### 通过 HTTP 控制 UI

控制 UI 需要安全上下文（HTTPS 或 localhost）来生成设备身份。

* Token/密码身份验证无法替代通过远程纯 HTTP 访问时的浏览器设备身份。请使用 HTTPS（例如 Tailscale Serve），或在 Gateway 主机上通过 `127.0.0.1` 打开 UI。
* `gateway.controlUi.dangerouslyDisableDeviceAuth`：已弃用的紧急解锁配置项。旧配置会保留经过身份验证、仅限配对的 Control UI 访问权限，以便进行修复；直到通过 HTTPS 或 localhost 重新打开浏览器，完成范围受限且明确的自配对迁移为止；请勿将其添加到当前配置中。
* 另外，成功通过 `gateway.auth.mode: "trusted-proxy"` 完成身份验证后，可以允许 **operator** Control UI 会话在没有设备身份的情况下访问。这不适用于 node-role Control UI 会话。

### 不安全／危险标志

`openclaw security audit` 会针对每个已启用、已知不安全／危险的调试开关抛出 `config.insecure_or_dangerous_flags`（每个标志一个发现项）。在生产环境中请保持这些项未设置。如果配置了审计抑制项，即使匹配的发现项移动到 `suppressedFindings`，`security.audit.suppressions.active` 仍会保留在活动输出中。

<AccordionGroup>
  <Accordion title="当前审计跟踪的标志">
    * `gateway.controlUi.dangerouslyAllowHostHeaderOriginFallback=true`
    * 从已停用的 `gateway.controlUi.dangerouslyDisableDeviceAuth=true` 导入的待处理控制 UI 设备身份验证迁移
    * `security.audit.suppressions configured (<count>)`
    * `hooks.gmail.allowUnsafeExternalContent=true`
    * `hooks.mappings[<index>].allowUnsafeExternalContent=true`
    * `tools.exec.applyPatch.workspaceOnly=false`
    * `plugins.entries.acpx.config.permissionMode=approve-all`
  </Accordion>

  <Accordion title="配置 schema 中所有 dangerous*/dangerously* 键">
    控制 UI 和浏览器：

    * `gateway.controlUi.dangerouslyAllowHostHeaderOriginFallback`
    * `gateway.controlUi.dangerouslyDisableDeviceAuth`（已停用的升级输入）
    * `browser.ssrfPolicy.dangerouslyAllowPrivateNetwork`

    通道名称匹配（捆绑和插件通道；如适用，也包括每个 `accounts.<accountId>`）：

    * `channels.discord.dangerouslyAllowNameMatching`
    * `channels.googlechat.dangerouslyAllowNameMatching`
    * `channels.msteams.dangerouslyAllowNameMatching`
    * `channels.slack.dangerouslyAllowNameMatching`
    * `channels.irc.dangerouslyAllowNameMatching`（插件通道）
    * `channels.mattermost.dangerouslyAllowNameMatching`（插件通道）
    * `channels.synology-chat.dangerouslyAllowNameMatching`（插件通道）
    * `channels.synology-chat.dangerouslyAllowInheritedWebhookPath`（插件通道）
    * `channels.zalouser.dangerouslyAllowNameMatching`（插件通道）

    网络暴露：

    * `channels.telegram.network.dangerouslyAllowPrivateNetwork`（也适用于每个账户）

    Docker 沙箱（默认值＋每个代理）：

    * `agents.defaults.sandbox.docker.dangerouslyAllowReservedContainerTargets`
    * `agents.defaults.sandbox.docker.dangerouslyAllowExternalBindSources`
    * `agents.defaults.sandbox.docker.dangerouslyAllowContainerNamespaceJoin`
  </Accordion>
</AccordionGroup>

## 部署和主机信任

* 网关主机启用全盘加密；如果主机由多人共享，优先为网关使用专用的操作系统用户账户。
* 已发布的软件包依赖锁定：源代码检出使用 `pnpm-lock.yaml`；已发布的 `openclaw` npm 软件包和 OpenClaw 自有的 npm 插件软件包包含 `npm-shrinkwrap.json`，因此安装时会使用发布版本中经过审核的传递依赖关系图，而不是在安装时重新解析一份全新的依赖关系图。这是供应链加固和发布可复现性的边界，并非沙箱——参见 [npm shrinkwrap](/gateway/security/shrinkwrap)。
* 安全文件操作：OpenClaw 使用 `@openclaw/fs-safe` 进行根目录边界内的文件访问、原子写入、归档提取、临时工作区和机密文件辅助操作。可选的原生加速默认**关闭**；设置 `OPENCLAW_FS_SAFE_NATIVE_MODE=auto` 可使用已安装的平台绑定，设置为 `require` 则在原生支持不可用时安全失败。详情参见：[安全文件操作](/gateway/security/secure-file-operations)。
* 共享 Slack 工作区风险：如果 Slack 中的所有人都可以向机器人发送消息，核心风险在于工具权限被委派——任何获准的发送者都可以在代理策略允许的范围内诱导工具调用（`exec`、浏览器、网络/文件工具）；来自某个发送者的提示词/内容注入可能影响共享状态、设备和输出；如果共享代理拥有敏感凭据/文件，任何获准的发送者都有可能通过使用工具来驱动数据外泄。对于团队工作流，应使用工具集最小化的独立代理/网关；涉及个人数据的代理应保持私有。
* 公司共享代理（可接受的模式）：当所有使用该代理的人员都处于同一信任边界内（例如同一个公司团队），且代理严格限定在业务范围内时，这种做法是可行的。应在专用机器/虚拟机/容器上运行，使用专用的操作系统用户 + 专用的浏览器/配置文件/账户，并且不要让该运行环境登录个人 Apple/Google 账户或个人密码管理器/浏览器配置文件。在同一运行环境中混用个人和公司身份会破坏隔离，并增加个人数据暴露风险。

## 磁盘上的密钥

假设 `~/.openclaw/`（或 `$OPENCLAW_STATE_DIR/`）下的任何内容都可能包含密钥或私人数据：

| 路径                                             | 内容                                                                                                                                                                                                                                                                                                                                                                                                                        |
| ---------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `openclaw.json`                                | 配置可能包含令牌（网关、远程网关）、提供商设置和允许列表。                                                                                                                                                                                                                                                                                                                                                                                             |
| `credentials/**`                               | 通道凭据（例如 WhatsApp 凭据）、配对允许列表、旧版 OAuth 导入数据。                                                                                                                                                                                                                                                                                                                                                                                |
| `state/openclaw.sqlite`                        | 共享运行时状态，包括原生 MCP OAuth 访问令牌／刷新令牌、动态客户端注册密钥和发现状态。                                                                                                                                                                                                                                                                                                                                                                          |
| `agents/<agentId>/agent/openclaw-agent.sqlite` | 每个代理的运行时状态，包括模型身份验证配置文件。                                                                                                                                                                                                                                                                                                                                                                                                  |
| `agents/<agentId>/agent/auth-profiles.json`    | 旧版模型身份验证迁移源；doctor 会将受支持的记录导入每个代理的 SQLite 数据库。                                                                                                                                                                                                                                                                                                                                                                            |
| `agents/<agentId>/agent/codex-home/**`         | 每个代理的 Codex 应用服务器账户、配置、技能、插件、原生线程状态和诊断信息（默认）。                                                                                                                                                                                                                                                                                                                                                                             |
| `$CODEX_HOME/**` 或 `~/.codex/**`               | 原生 Codex 运行时状态。普通工具框架仅在明确设置 `plugins.entries.codex.config.appServer.homeScope: "user"` 时访问它。单独的监督连接会在其解析出的主目录作用域为 `"user"` 时访问它；对于未设置该值的 stdio 或 Unix，这是默认值。包含原生 Codex 账户、配置、插件和线程存储。监督功能会列出源元数据，并在该连接上保留持续 Chat 的规范原生分支及后续轮次；分支会将有界的持久化用户和助手历史记录复制到经过身份验证且锁定模型的 OpenClaw Chat 中。仅为所有者控制的网关启用。请参阅 [Codex 工具框架](/plugins/codex-harness#share-threads-with-codex-desktop-and-cli) 和 [Codex 监督](/plugins/codex-supervision)。 |
| `secrets.json`（可选）                             | 由 `file` SecretRef 提供商（`secrets.providers`）使用的基于文件的密钥载荷。                                                                                                                                                                                                                                                                                                                                                                  |
| `agents/<agentId>/agent/auth.json`             | 旧版兼容文件；发现静态 `api_key` 条目时会将其清除。                                                                                                                                                                                                                                                                                                                                                                                           |
| `agents/<agentId>/agent/openclaw-agent.sqlite` | 每个代理的运行时状态，包括可能包含私人消息和工具输出的会话记录及转录内容。                                                                                                                                                                                                                                                                                                                                                                                     |
| `agents/<agentId>/sessions/**`                 | 旧版会话迁移源和存档，可能包含私人消息和工具输出。                                                                                                                                                                                                                                                                                                                                                                                                 |
| 捆绑插件包                                          | 已安装的插件（及其 `node_modules/`）。                                                                                                                                                                                                                                                                                                                                                                                               |
| `sandboxes/**`                                 | 工具沙盒工作区；可能会积累在沙盒内读取或写入的文件副本。                                                                                                                                                                                                                                                                                                                                                                                              |

### 凭据存储映射

也可用于备份决策：

* WhatsApp：`~/.openclaw/credentials/whatsapp/<accountId>/creds.json`
* Telegram 机器人令牌：配置／环境变量或 `channels.telegram.tokenFile`（仅限常规文件；拒绝符号链接）
* Discord 机器人令牌：配置／环境变量或 SecretRef（env／file／exec／store 提供程序）
* Slack 令牌：配置／环境变量（`channels.slack.*`）
* 配对允许列表：`~/.openclaw/credentials/<channel>-allowFrom.json`（默认账户）／`<channel>-<accountId>-allowFrom.json`（非默认账户）
* 模型身份验证配置文件：`~/.openclaw/agents/<agentId>/agent/openclaw-agent.sqlite`（`auth_profile_store`）
* MCP OAuth 会话：`~/.openclaw/state/openclaw.sqlite`（`mcp_oauth_stores`）
* 旧版 OAuth 导入：`~/.openclaw/credentials/oauth.json`

加固：保持严格权限（目录使用 `700`，文件使用 `600`）；在网关主机上使用全盘加密；如果主机是共享的，优先使用专用的操作系统用户账户。

### 文件权限

* `~/.openclaw/openclaw.json`：`600`（仅用户可读写）
* `~/.openclaw`：`700`（仅用户可访问）

`openclaw doctor` 可以发出警告并建议收紧这些权限。

### 工作区 `.env` 文件

OpenClaw 会为代理和工具加载工作区本地的 `.env` 文件，但绝不会让它们悄悄覆盖网关运行时控制：

* 来自不受信任工作区 `.env` 文件的提供商凭证环境变量会被阻止——例如 `GEMINI_API_KEY`、`GOOGLE_API_KEY`、`XAI_API_KEY`、`MISTRAL_API_KEY`、`GROQ_API_KEY`、`DEEPSEEK_API_KEY`、`PERPLEXITY_API_KEY`、`BRAVE_API_KEY`、`TAVILY_API_KEY`、`EXA_API_KEY`、`FIRECRAWL_API_KEY`，以及已安装的受信任插件声明的提供商身份验证密钥。请改为将提供商凭证放入网关进程环境、`~/.openclaw/.env`（`$OPENCLAW_STATE_DIR/.env`）、配置中的 `env` 块，或通过可选的登录 shell 导入。
* 任何以 `OPENCLAW_` 开头的密钥都会被阻止出现在不受信任工作区的 `.env` 文件中，从而保留整个运行时命名空间，确保未来的 `OPENCLAW_*` 控制项默认采用失败关闭，而不是从已提交到仓库或由攻击者提供的 `.env` 内容中被静默继承。
* 工作区 `.env` 覆盖同样会被禁止设置频道和提供商端点路由配置（例如 `MATRIX_HOMESERVER`、`MATTERMOST_URL`、`IRC_HOST`、`SYNOLOGY_CHAT_INCOMING_URL`、`AZURE_SPEECH_ENDPOINT`，以及其他以 `_ENDPOINT` 结尾的密钥），这样克隆的工作区就无法通过本地端点配置重定向捆绑连接器的流量。这些配置必须来自网关进程环境、全局运行时 dotenv、显式配置或 `env.shellEnv`。
* 受信任的进程／操作系统环境变量、全局运行时 dotenv、配置中的 `env`，以及已启用的登录 shell 导入仍然有效——这只限制工作区 `.env` 文件的加载。

工作区 `.env` 文件通常与代理代码放在一起，容易被误提交，或者被工具写入；阻止提供商凭证可以防止克隆的工作区替换为攻击者控制的提供商账户。

### 日志和转录

OpenClaw 将会话转录存储在磁盘上的 `~/.openclaw/agents/<agentId>/sessions/*.jsonl` 中，用于会话连续性和可选的记忆索引——任何拥有文件系统访问权限的进程/用户都可以读取它们。请将磁盘访问视为信任边界，并锁定 `~/.openclaw` 的权限；在单独的操作系统用户或主机下运行代理，以获得更强的隔离。

网关日志可能包含工具摘要、错误和 URL；会话转录可能包含粘贴的密钥、文件内容、命令输出和链接。

* 日志/转录脱敏始终启用，无法通过配置禁用。
* 通过 `logging.redactPatterns` 为你的环境添加自定义模式（令牌、主机名、内部 URL）。
* 分享诊断信息时，优先使用 `openclaw status --all`（可直接粘贴，且已脱敏），而不是原始日志。
* 如果不需要长期保留，请清理旧的会话转录和日志文件。

详情： [日志](/gateway/logging)

## 安全基线（复制/粘贴）

```json5 theme={"theme":{"light":"min-light","dark":"min-dark"}}
{
  gateway: {
    mode: "local",
    bind: "loopback",
    port: 18789,
    auth: { mode: "token", token: "your-long-random-token" },
  },
  channels: {
    whatsapp: {
      dmPolicy: "pairing",
      groups: { "*": { requireMention: true } },
    },
  },
}
```

这会让 Gateway 保持私有，要求通过私信配对，并避免始终在线的群组机器人。为了更安全地执行工具，也建议为任何非所有者代理添加沙箱，并禁止危险工具（参见上面的“每个代理的访问配置文件”）。

### 分开使用号码（WhatsApp、Signal、Telegram）

对于基于电话号码的渠道，建议把助手运行在一个与你个人号码不同的独立号码上，这样个人对话就能保持私密，而机器人号码则在自己的边界内处理自动化任务。

## 事件响应

### 遏制

1. 停止它：停止 macOS 应用（如果它在监督 Gateway）或终止你的 `openclaw gateway` 进程。
2. 关闭暴露：将 `gateway.bind: "loopback"`（或禁用 Tailscale Funnel／Serve），直到你弄清楚发生了什么。
3. 冻结访问：将有风险的 DM／群组切换为 `dmPolicy: "disabled"` ／要求提及，并移除任何 `"*"` 允许全部的条目。

### 轮换（若秘密泄露则假定已被攻破）

1. 轮换 Gateway 认证（`gateway.auth.token` ／ `OPENCLAW_GATEWAY_PASSWORD`）并重启。
2. 轮换远程客户端密钥（`gateway.remote.token` ／ `.password`），适用于任何可以调用 Gateway 的机器。
3. 轮换提供商／API 凭证（WhatsApp 凭证、Slack／Discord token、`auth-profiles.json` 中的模型／API 密钥，以及在使用时加密的秘密载荷值）。

### 审计

1. 检查 Gateway 日志，使用 `openclaw logs`（对于命名配置文件，使用 `openclaw --profile <profile> logs`）。默认路径为 `/tmp/openclaw/openclaw-YYYY-MM-DD.log`；除非 `logging.file` 覆盖该路径，否则命名配置文件使用 `/tmp/openclaw/openclaw-<profile>-YYYY-MM-DD.log`。
2. 查看相关的转录记录：`~/.openclaw/agents/<agentId>/sessions/*.jsonl`。
3. 查看近期可能扩大访问范围的配置更改：`gateway.bind`、`gateway.auth`、DM／群组策略、`tools.elevated`、插件更改。
4. 重新运行 `openclaw security audit --deep`，并确认关键发现已解决。

### 收集用于报告

* 时间戳、Gateway 主机 OS + OpenClaw 版本。
* 会话转录 + 一段简短的日志尾部（脱敏后）。
* 攻击者发送了什么，以及代理做了什么。
* Gateway 是否暴露到了 loopback 之外（LAN／Tailscale Funnel／Serve）。

## 密钥扫描

CI 会在整个仓库上运行 pre-commit 的 `detect-private-key` 钩子。如果它失败，请移除或轮换已提交的密钥材料，然后在本地复现：

```bash theme={"theme":{"light":"min-light","dark":"min-dark"}}
pre-commit run --all-files detect-private-key
```

## 报告安全问题

在 OpenClaw 中发现了漏洞？请负责任地报告：

1. 电子邮件：[security@openclaw.ai](mailto:security@openclaw.ai)
2. 在修复前请勿公开发布。
3. 我们会致谢您的贡献（除非您希望匿名）。
