09 · Channel 与安全:谁能进来、能做什么
从 OpenClaw 官方安全模型出发,拆清 Channel 路由、DM 配对、群组门控、工具权限、沙箱和 Gateway 暴露。
OpenClaw 的安全问题不能只问“模型聪不聪明”。真正要问的是三件事:
谁能触发 Agent?Agent 能调用哪些工具?这些工具在哪里运行?
这三件事分别落在 Channel access、Tool policy、Sandbox / Elevated 上。系统提示词和 prompt injection 防御只能降低风险,不能替代这些硬边界。
这一篇的核心判断:安全边界不在模型嘴上,而在 Gateway 入口、Session 隔离、Tool policy、Sandbox 和网络暴露面上。
flowchart LR
Sender["外部发送者"] --> Access["Channel access<br/>谁能进来"]
Access --> Route["Routing<br/>进哪个 Agent"]
Route --> Context["Session / Context<br/>看到哪些上下文"]
Context --> Policy["Tool policy<br/>能调用哪些工具"]
Policy --> Sandbox["Sandbox / Elevated<br/>在哪里执行"]
Sandbox --> Host["Gateway host<br/>真实资源"]
style Access fill:#fef3c7,stroke:#f59e0b,stroke-width:2px
style Route fill:#dbeafe,stroke:#3b82f6,stroke-width:2px
style Context fill:#dbeafe,stroke:#3b82f6,stroke-width:2px
style Policy fill:#dcfce7,stroke:#22c55e,stroke-width:2px
style Sandbox fill:#fee2e2,stroke:#ef4444,stroke-width:2px
style Host fill:#f3f4f6,stroke:#6b7280,stroke-width:2px
1. 官方安全模型:先定 trust boundary
OpenClaw 官方安全文档明确把默认模型定义为个人助理部署:一个 Gateway 对应一个可信 operator boundary,可以有多个 Agent,但不把同一个 Gateway 当成多个敌对租户之间的强隔离边界。
这句话要先理解:一个 shared gateway 不适合承载互不信任的敌对用户。
如果你要让陌生人、客户、外部用户共享一个能跑工具的 Agent,不应该只靠 prompt 或 allowlist。更稳妥的拆法是:
- Gateway 控制面:分 Gateway。
- 凭据和 channel token:分 credentials。
- OS 级资源:分 OS user、host 或 VPS。
- 工具执行能力:每个 Agent 只拿自己需要的 sandbox 和 tool policy。
如果多个不可信用户能给同一个 tool-enabled Agent 发消息,官方建议把他们视为共享了这个 Agent 的 delegated tool authority。也就是说:他们不是彼此隔离的安全主体。
shared Gateway 可以是个人助理系统,不应该被误当成强多租户隔离平台。
2. Channel 只负责消息入口和回路
Channel 是消息入口抽象。Telegram、WhatsApp、Discord、Slack、Signal、iMessage、LINE、IRC、Google Chat 以及扩展渠道进来的消息,会被 Gateway 标准化,再进入 Agent。
但不要误解为“模型自己决定发回哪里”。官方 Channel Routing 文档说得很清楚:
回复回到原消息来源;模型不选择 channel;路由由 host configuration 决定。
几个关键词:
Channel:消息平台,例如 telegram、whatsapp、discord、slack;安全上看平台入口是否允许。AccountId:同一 channel 下的账号实例;安全上看多账号默认账号是否明确。AgentId:独立 workspace + session store;安全上看消息最终进哪个 Agent。SessionKey:上下文桶;安全上看是否串上下文、是否影响工具运行姿态。
多账号场景要设置明确默认账号,例如 channels.telegram.defaultAccount 或 accounts.default。否则 fallback routing 可能拿到第一个 normalized account id,这在安全审计里很难解释。
3. 路由是确定性的,不是模型猜的
OpenClaw 选择 Agent 的顺序是确定规则:
| 优先级 | 匹配规则 | 用途 |
|---|---|---|
| 1 | Exact peer match | 精确发送者或会话绑定 |
| 2 | Parent peer match | thread inheritance |
| 3 | Discord guild + roles match | Discord 角色分流 |
| 4 | Discord guild match | Discord 服务器分流 |
| 5 | Slack team match | Slack team 分流 |
| 6 | Account match | 同一平台多账号分流 |
| 7 | Channel match | 按平台默认分流 |
| 8 | Default agent | 兜底 Agent |
Session key 形态也由来源决定:
- Direct DM:
agent:agentId:mainKey。 - Group:
agent:agentId:channel:group:id。 - Room/channel:
agent:agentId:channel:channel:id。 - Slack thread:base key 后追加
thread:threadId。 - Telegram topic:group key 内包含
topic:topicId。
注意:DM 默认可能落入 main session,但外部 DM 的 sandbox 和 tool policy 会使用派生 runtime key,不会被当成本地 main-session run 处理。这个细节是为了避免“外部渠道消息看起来像本机主会话”的安全错觉。
路由确定性是安全资产。能解释一条消息为什么进某个 Agent,后续才谈得上审计和收紧。
4. DM access:pairing 是默认安全起点
所有当前支持 DM 的渠道都有 DM policy。它在消息被处理前先挡住入站 DM。
四种策略:
dmPolicy | 行为 | 风险判断 |
|---|---|---|
pairing | 默认。未知发送者拿到短码,owner approve 前消息不会被处理 | 私人 Agent 的默认安全起点 |
allowlist | 只允许 allowFrom 或 pairing allow-store 中的发送者 | 适合固定联系人 |
open | 允许所有入站 DM,必须显式 allowFrom: ["*"] | 只适合非常受限的工具能力 |
disabled | 忽略所有入站 DM | 适合关闭外部私信入口 |
Pairing 的官方细节:
- 配对码:8 位、大写、避开易混字符
0O1I。 - 过期时间:1 小时。
- 同一 sender:约每小时只会创建一次新请求。
- pending 数量:每个 channel 默认最多 3 个 pending requests。
- approve 前:未知 sender 的消息不会进入 Agent。
审批命令:
openclaw pairing list telegram
openclaw pairing approve telegram PAIRCODEDM 配对状态在 Gateway host 上,默认路径:
默认文件包括 ~/.openclaw/credentials/channel-pairing.json、~/.openclaw/credentials/channel-allowFrom.json 和 ~/.openclaw/credentials/channel-accountId-allowFrom.json。
这些文件是访问控制数据,按敏感文件处理。
5. DM isolation:不要把多人 DM 放进一个上下文
DM access 解决“谁能说话”。DM isolation 解决“谁和谁共享上下文”。
如果只有你一个人用私人 Agent,session.dmScope: "main" 可以保持连续性。
如果多个人能 DM:
{
"session": {
"dmScope": "per-channel-peer"
}
}官方的 shared inbox quick rule:
- 多人可 DM:用
per-channel-peer。 - 多账号 channel:用
per-account-channel-peer。 - 固定联系人:保持
dmPolicy: "pairing"或严格 allowlist。 - shared inbox + 工具能力:不要和 broad tool access 放在一起。
这仍然不是敌对多租户隔离。它只是把 cooperative shared inbox 做得更稳。
dmPolicy 管“谁能进来”,dmScope 管“谁和谁共享上下文”。这两个必须一起看。
6. Group access:allowlist 先于 mention
群组比 DM 更危险,因为消息来源更多,历史上下文更杂。
官方 Groups 文档的默认行为:
groupPolicy默认allowlist:群组不是默认全开放入口。- 群组回复默认需要 mention:不被 @ 时通常不应主动回复。
- Heartbeat 会跳过 group sessions:周期提醒不应自动打扰群组。
群组消息的判断顺序:
- 先看
groupPolicy是disabled、allowlist还是open,决定群组入口是否进入处理链路。 - 再看 Group allowlists 是否允许这个群、房间或 sender。
- 最后看
requireMention/ activation 是否允许触发回复。
groupPolicy 和 mention gating 是两件事:
groupPolicy决定这个群组或房间能不能进入处理链路。requireMention决定是否必须 @ 到 bot 才触发回复。
安全默认:
{
"channels": {
"whatsapp": {
"groupPolicy": "allowlist",
"groupAllowFrom": ["+15551234567"],
"groups": {
"*": { "requireMention": true }
}
}
}
}DM pairing approval 不等于 group authorization。批准某人私信,只是让他能 DM;不代表他能在群里触发命令。
7. Context visibility:触发权限不等于上下文过滤
官方安全文档把两件事分开:
- Trigger authorization 问“谁能触发 Agent”,例如 sender、group、room 是否 allowlisted。
- Context visibility 问“哪些补充上下文进入模型输入”,例如 quote、thread history、forward metadata。
补充上下文包括 reply body、quoted text、thread history、forwarded metadata。默认 contextVisibility: "all" 会尽量保持正常聊天体验,但这不代表所有 quoted/history 内容都经过了同等 allowlist 过滤。
可选模式:
contextVisibility | 行为 | 适合场景 |
|---|---|---|
all | 默认,按收到的上下文保留 | 私人或可信群组 |
allowlist | 只保留 active allowlist 允许 sender 的补充上下文 | 更强上下文过滤 |
allowlist_quote | 类似 allowlist,但保留显式 quote/reply 例外 | 需要回复引用上下文,但仍要收紧 |
这对群聊尤其重要:一个非 allowlisted sender 不能触发 Agent,不代表他的历史消息永远不会以 thread/quote context 形式被模型看到。需要强边界时,把 contextVisibility 配到 channel 或具体 room/conversation。
触发权限不是上下文过滤。能不能让 Agent 开口,和哪些历史内容进入模型,是两条不同的安全链路。
8. 工具安全分三层
OpenClaw 有三个相关但不同的控制:
- Sandbox:决定工具在哪里运行,比如 host、Docker、SSH、OpenShell;这是运行环境边界。
- Tool policy:决定哪些工具存在、可调用;这是能力边界。
- Elevated:决定 sandboxed exec 是否有出沙箱逃生口;只影响
exec。
Sandbox mode:
| Sandbox mode | 行为 | 适合场景 |
|---|---|---|
off | 全部工具在 host 上运行 | 只适合可信个人入口 |
non-main | 只有 non-main sessions sandboxed | 群组、channel、外部入口常见选择 |
all | 所有 session 都 sandboxed | 更严格的默认隔离 |
Tool policy 规则:
deny永远优先:明确禁止不能被后续 allow 覆盖。allow非空时,没列入的工具都被 blocked:allowlist 是收紧模式。/exec不能覆盖被 tool policy deny 的exec:用户命令不能越过硬 policy。- Provider-specific policy 可覆盖:可以按 provider 或 provider/model 定制。
- Sandbox tool policy 只在 sandboxed 时生效:要先确认 session 是否真的 sandboxed。
Elevated 规则:
on/ask:出沙箱但保留 approvals,需要人工确认。full:出沙箱并跳过 exec approvals,风险最高。- 未启用或 sender 未 allowlisted:不允许 elevated,默认更稳。
Elevated 不授予额外工具,不覆盖 tool allow/deny;它只在 agent sandboxed 且影响 exec 时改变运行位置。
调试实际生效规则:
openclaw sandbox explain
openclaw sandbox explain --session agent:main:main
openclaw sandbox explain --agent work
openclaw sandbox explain --json9. Sandbox bind mounts 是真实穿透口
Docker sandbox 不是魔法墙。你挂载什么,容器里就能看到什么。
官方安全要点:
docker.binds会穿透 sandbox filesystem,挂进去的路径,容器里就能看见。- 不写 mode 时默认 read-write,敏感路径优先
ro。 workspaceAccess独立于 bind mode,workspace 权限和额外挂载权限分开判断。- 绑定
/var/run/docker.sock等于把 host 控制权交给 sandbox。 - Symlink-parent escapes 已有校验,但仍不要把敏感目录放进 allowed roots。
群组和公共 Agent 的更稳写法:
{
"agents": {
"defaults": {
"sandbox": {
"mode": "non-main",
"scope": "session",
"workspaceAccess": "none",
"docker": {
"binds": ["/home/user/PublicDocs:/data:ro"]
}
}
}
},
"tools": {
"sandbox": {
"tools": {
"allow": ["group:messaging", "group:sessions"],
"deny": ["group:runtime", "group:fs", "group:ui", "nodes", "cron", "gateway"]
}
}
}
}这不是为了“让模型更乖”,而是让模型就算被诱导,也没有能力碰 host 文件和 shell。
Sandbox 不是口头承诺。真正要检查的是 bind mounts、workspaceAccess、tool allow/deny 和 elevated gates 的组合。
10. Prompt injection 没有被解决
Prompt injection 是攻击者把恶意指令塞进消息、网页、邮件、附件、日志或文件,让模型把外部内容误当成操作指令。
官方安全文档的立场很现实:
强 system prompt 只是 soft guidance;硬边界来自 tool policy、exec approvals、sandboxing、channel allowlists。
应该视为不可信的内容:
- “读这个文件或 URL,然后照里面说的做。”风险是外部内容伪装成操作指令。
- “忽略 system prompt 或安全规则。”风险是试图覆盖上层约束。
- “输出 hidden instructions 或 tool outputs。”风险是诱导泄漏内部上下文。
- “粘贴
~/.openclaw或日志的完整内容。”风险是诱导泄漏配置和 transcript。 - 网页、邮件、附件、转发消息、群聊历史、粘贴的日志和代码,都可能把外部输入混入模型上下文。
实际防御:
- 入口:入站 DM 用 pairing 或 allowlist。
- 群组:用 mention gating,不做 public room always-on bot。
- Agent profile:触碰不可信内容的 Agent 用 read-only 或 tool-disabled profile。
- 高风险工具:
exec、browser、web_fetch、web_search只给可信 Agent。 - 解释器:需要 allowlist 时,启用
tools.exec.strictInlineEval。 - 秘密:不放进 prompt,放在 Gateway host 的 env/config 中。
- 模型:Tool-enabled Agent 选更新、更强的 instruction-hardened model。
不要承诺“防住所有 prompt injection”。正确目标是:注入即使成功,也不能变成文件、shell、网络、浏览器、凭据泄露的真实动作。
11. Browser 和插件也属于攻击面
Browser control 风险不低。Host browser profile 可能有登录态、cookie、后台账号。官方建议:
- 给 Agent 用专用 profile,避免复用个人登录态。
- 不要指向日常浏览器 profile,cookie、后台账号、历史记录都可能暴露。
- Sandboxed agents 不默认启用 host browser control,否则会绕回 host 侧高权限面。
- 严格环境收紧 Browser SSRF policy,private/internal destinations 默认禁掉,再用 allowlist 开例外。
Plugin 也不是普通配置。Plugin 在 Gateway 进程内运行,应该当作可信代码:
- 只装可信来源,因为 Plugin 在 Gateway 进程内运行。
- 用
plugins.allow做显式 allowlist,避免随意加载。 - 安装和更新前看清配置,配置本身可能扩大权限。
- 更新 plugin 后重启 Gateway,确保加载状态一致。
- 谨慎使用
dangerously-force-unsafe-install,只作为 false positive 的 break-glass。
12. Gateway 暴露面:默认 loopback,不要裸奔
Gateway 默认端口是 18789,WebSocket 和 HTTP 共用这个端口。HTTP surface 包括 Control UI、canvas host 等。
安全规则:
gateway.bind: "loopback"是默认值,只允许本地客户端连接。"lan"、"tailnet"、"custom"都会扩大攻击面。- 非 loopback bind 必须配 Gateway auth、真实 firewall、可信反代或 Tailscale 方案。
- Tailscale Serve 优先于 LAN bind。
- 必须 LAN bind 时,firewall 只允许极小 source IP 集合。
- unauthenticated
0.0.0.0不应出现。
最小安全基线:
{
"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 }
}
}
}
}13. 日志、transcripts、配置都是敏感数据
即使访问控制正确,日志和 transcript 也会泄露信息。
官方提醒的敏感位置:
~/.openclaw/openclaw.json:Gateway、channel、tool、auth 配置。~/.openclaw/agents/agentId/sessions/sessions.json:session 路由和状态。~/.openclaw/agents/agentId/sessions/*.jsonl:transcript、工具调用和结果。~/.openclaw/sandboxes/:sandbox 运行产物。/tmp/openclaw/openclaw-YYYY-MM-DD.log:日志和排障信息。
建议:
~/.openclaw目录权限保持700,限制本机其他用户读取。openclaw.json保持600,避免配置泄露。- 保持
logging.redactSensitive: "tools",对工具输出脱敏。 - 增加
logging.redactPatterns,遮盖内部域名、token、hostnames。 - 对外排障优先给
openclaw status --all,避免直接贴 raw logs。 - 清理旧 transcripts 和 logs,降低历史泄露面。
- 共享 host 用专用 OS user 跑 Gateway,限制横向读取。
14. 安全审计和应急
改配置、开新 channel、暴露网络面之后,跑:
openclaw security audit
openclaw security audit --deep
openclaw security audit --json--fix 只做窄修复:收紧常见 open group policies、恢复敏感日志脱敏、修 state/config/include-file 权限等。不要把它当成全自动安全加固。
如果怀疑暴露或泄露:
- Contain:停 Gateway,临时改回
gateway.bind: "loopback",DM/group 改disabled或 require mention,并移除"*"allow-all。 - Rotate:换
gateway.auth.token或OPENCLAW_GATEWAY_PASSWORD,换 remote client token/password,换 channel tokens、model keys、auth-profiles、encrypted secrets。 - Audit:查 Gateway logs、相关 session transcripts 和近期 config diff,再重跑
openclaw security audit --deep。
15. 给 Agent 的实践任务
把这组要求发给 OpenClaw Agent,让它审计自己的入口安全:
- 只读审计当前 OpenClaw Gateway 的 Channel 与安全配置,不要直接修改文件。
- 运行
openclaw security audit --deep,并按 critical / warn / info 分类总结。 - 检查
gateway.bind、gateway.auth、gateway.port,说明是否存在非 loopback 暴露或弱认证。 - 检查所有 channels 的
dmPolicy、allowFrom、groupPolicy、groups、groupAllowFrom、requireMention。 - 检查
session.dmScope;如果多用户 DM 仍然使用main,指出风险。 - 检查
contextVisibility是否适合群聊或公开频道。 - 运行
openclaw sandbox explain --json,说明 sandbox mode、workspaceAccess、tool allow/deny、elevated gates。 - 检查是否给公共或群组 Agent 开了
exec、browser、web_fetch、web_search、gateway、cron、sessions_send、sessions_spawn。 - 检查日志、transcripts、credentials、pairing store 的权限和敏感信息暴露风险。
- 输出最小修复建议,按“必须修 / 建议修 / 可观察”分组。
16. 本章自检
读完这一章,你应该能回答:
- OpenClaw 为什么不把一个 shared Gateway 当成敌对多租户隔离边界?
- Channel routing 为什么是确定性的?
dmPolicy: "pairing"和session.dmScope分别解决什么问题?- 为什么 DM pairing approval 不等于 group authorization?
groupPolicy、group allowlist、mention gating 的判断顺序是什么?- Trigger authorization 和 context visibility 的区别是什么?
- Sandbox、tool policy、elevated 分别控制什么?
- 为什么
deny比allow优先? - Prompt injection 为什么不能靠 system prompt 彻底解决?
- 为什么 Gateway 默认应该保持 loopback?
过关标准:能把一次外部消息拆成“入口授权 → 路由 → 上下文可见性 → 工具策略 → 运行环境 → 日志与配置保护”六层检查。
17. 接下来去哪
10 · 设计复盘
把 Channel、Session、Memory、Tools 和安全边界收束成一次架构评审。
08 · Session 与 Heartbeat
回到上一篇,理解 session、task、heartbeat 和 schedule 的上下文边界。
官方教程:远程与安全
继续看 Gateway 暴露、认证、远程控制和运行边界的官方配置口径。