AI 程式設計教程中文版
從原理到實戰

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.defaultAccountaccounts.default。否則 fallback routing 可能拿到第一個 normalized account id,這在安全審計裡很難解釋。

3. 路由是確定性的,不是模型猜的

OpenClaw 選擇 Agent 的順序是確定規則:

優先順序匹配規則用途
1Exact peer match精確傳送者或會話繫結
2Parent peer matchthread inheritance
3Discord guild + roles matchDiscord 角色分流
4Discord guild matchDiscord 伺服器分流
5Slack team matchSlack team 分流
6Account match同一平臺多賬號分流
7Channel match按平臺預設分流
8Default 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 PAIRCODE

DM 配對狀態在 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:週期提醒不應自動打擾群組。

群組訊息的判斷順序:

  1. 先看 groupPolicydisabledallowlist 還是 open,決定群組入口是否進入處理鏈路。
  2. 再看 Group allowlists 是否允許這個群、房間或 sender。
  3. 最後看 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 --json

9. 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。
  • 高風險工具:execbrowserweb_fetchweb_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 許可權等。不要把它當成全自動安全加固。

如果懷疑暴露或洩露:

  1. Contain:停 Gateway,臨時改回 gateway.bind: "loopback",DM/group 改 disabled 或 require mention,並移除 "*" allow-all。
  2. Rotate:換 gateway.auth.tokenOPENCLAW_GATEWAY_PASSWORD,換 remote client token/password,換 channel tokens、model keys、auth-profiles、encrypted secrets。
  3. Audit:查 Gateway logs、相關 session transcripts 和近期 config diff,再重跑 openclaw security audit --deep

15. 給 Agent 的實踐任務

把這組要求發給 OpenClaw Agent,讓它審計自己的入口安全:

  1. 只讀審計當前 OpenClaw Gateway 的 Channel 與安全配置,不要直接修改檔案。
  2. 執行 openclaw security audit --deep,並按 critical / warn / info 分類總結。
  3. 檢查 gateway.bindgateway.authgateway.port,說明是否存在非 loopback 暴露或弱認證。
  4. 檢查所有 channels 的 dmPolicyallowFromgroupPolicygroupsgroupAllowFromrequireMention
  5. 檢查 session.dmScope;如果多使用者 DM 仍然使用 main,指出風險。
  6. 檢查 contextVisibility 是否適合群聊或公開頻道。
  7. 執行 openclaw sandbox explain --json,說明 sandbox mode、workspaceAccess、tool allow/deny、elevated gates。
  8. 檢查是否給公共或群組 Agent 開了 execbrowserweb_fetchweb_searchgatewaycronsessions_sendsessions_spawn
  9. 檢查日誌、transcripts、credentials、pairing store 的許可權和敏感資訊暴露風險。
  10. 輸出最小修復建議,按“必須修 / 建議修 / 可觀察”分組。

16. 本章自檢

讀完這一章,你應該能回答:

  1. OpenClaw 為什麼不把一個 shared Gateway 當成敵對多租戶隔離邊界?
  2. Channel routing 為什麼是確定性的?
  3. dmPolicy: "pairing"session.dmScope 分別解決什麼問題?
  4. 為什麼 DM pairing approval 不等於 group authorization?
  5. groupPolicy、group allowlist、mention gating 的判斷順序是什麼?
  6. Trigger authorization 和 context visibility 的區別是什麼?
  7. Sandbox、tool policy、elevated 分別控制什麼?
  8. 為什麼 denyallow 優先?
  9. Prompt injection 為什麼不能靠 system prompt 徹底解決?
  10. 為什麼 Gateway 預設應該保持 loopback?

過關標準:能把一次外部訊息拆成“入口授權 → 路由 → 上下文可見性 → 工具策略 → 執行環境 → 日誌與配置保護”六層檢查。

17. 接下來去哪

18. 官方資料

本頁目錄