OpenClaw 可能把内部 completion payload 直接泄漏到用户聊天:怎么确认、怎么止损
OpenClaw News 编辑部
OpenClaw 新提交的一份 bug 报告指出:系统在某些场景下,可能把运行时内部 completion / announce 文本直接发送到终端用户聊天,而不是先重写成正常的助手口吻。
来源 Issue: openclaw/openclaw#61433
这个问题麻烦的地方,不只是“难看”。它可能把本该留在系统内部的内容暴露出去,例如:
- 本地文件路径
- 路由/投递说明
- completion 事件包装文本
- 运行时元数据片段
报告中怀疑,影响面不止一个场景,而是可能落在同一条完成态投递边界上,包括:
- isolated cron 的 announce 投递
- subagent 完成后的回传 announce
- 其他复用同类 follow-up / completion 路径的运行时事件
这个故障长什么样
正常情况下,用户最终应该只看到一条干净的提醒或总结。
但命中这个问题时,用户收到的消息里,除了最终要发给人的那句话,还可能混入:
- 任务过程中写入的文件路径
- 目标渠道/路由说明
- 内部 completion 事件的包装文本
- 不应该面向用户暴露的元数据段落
这里有个非常关键的运维判断:底层任务本身未必失败。
也就是说,真正出问题的,不一定是“任务没跑成”,而更像是内部完成态 → 用户可见消息这一跳的重写/净化边界失效了。
为什么这事值得重视
1)它会把不该给用户看的内部细节带出去
哪怕泄漏的不是绝对敏感信息,依然可能暴露:
- 本地目录结构
- 渠道路由方式
- 内部事件命名和运行机制
- 会让用户困惑的系统实现细节
对生产环境来说,这些都不该直接出现在面向用户的提醒里。
2)它会直接打击自动化的可信度
比如一个睡前提醒、本该很干净,结果却夹带内部路径和运行摘要。用户看到一次,后面就会开始怀疑所有后台自动化都“不稳”。
3)它很容易被误判成别的问题
很多团队第一反应会怀疑:
- 是不是 Telegram/Feishu/Discord 适配器有问题?
- 是不是模型自己乱说?
- 是不是 prompt 写坏了?
但从这份 issue 的描述看,更像是 announce / completion 的共享重写边界出了问题,而不是单一渠道或单个 prompt 的问题。
为什么说这不像“单纯提示词写得差”
OpenClaw 的 subagents 文档其实已经明确描述了预期行为:
- completion handoff 属于运行时内部上下文
- 请求方代理应该把它重写成正常助手口吻
- 不应该把原始内部元数据原样转发到用户聊天
参考文档: docs/tools/subagents.md
也就是说,项目设计上本来就区分了两层:
- 给系统编排用的内部 completion 上下文
- 给最终用户看的净化后消息
正因为文档已经明确这个边界,所以这份 issue 看起来更像是真 bug,而不是“使用者 prompt 没写好”。
怎么判断你是不是遇到了同类问题
如果同时满足下面几条,基本就该往这个方向排查:
- 后台任务本身看起来是成功完成的
- 最终用户侧收到的消息里,混进了明显不该出现的内部文本
- 这些文本包含文件路径、路由标记、wrapper、completion framing 之类正常助手不会说的话
- 症状主要出现在 cron announce、subagent completion 或类似的自动回传链路上
一个务实的确认方法:
- 触发一个受控的后台任务,让它先写一个文件,再回一条很短的最终消息。
- 对比“你期望用户收到的话”和“用户实际收到的话”。
- 如果实际消息里额外夹带了内部运行摘要,基本就是同类问题。
现在该怎么止损
1)把“任务是否成功”与“最终消息是否干净”拆开判断
不要因为最终消息长得不对,就立刻认定整个任务失败。
先分开看两件事:
- 任务到底有没有跑完
- 交付给用户的最后一条消息有没有被污染
这是两个不同层面的故障。
2)先把最终用户消息收窄到最小
在修复落地前,尽量让面向用户的完成态消息:
- 只保留一条简短总结
- 不包含文件路径
- 不包含内部步骤说明
- 不包含投递/路由措辞
这样即便边界再次失效,泄漏面也会小一些。
3)优先排查那些“会先写文件、再发结果”的自动化
风险更高的流程通常包括:
- 先把产物写到磁盘,再顺手把路径带进总结
- 依赖渠道/线程/路由上下文做投递
- 最终发给用户的内容不是单句,而是一整段运行摘要
如果你有对外提醒、日报、告警、睡前提醒等场景,值得先做一次抽查。
4)补证据时,尽量保留“期望输出 vs 实际输出”对照
对维护者最有帮助的材料通常包括:
- OpenClaw 版本
- 触发路径:cron、subagent,还是其他 completion 事件
- 用户实际看到的完整文本
- 原本期望发给用户的简短文本
- 是否跨多个渠道都能复现
注意脱敏,但要保留足够结构,方便确认问题确实发生在内部/外部边界上。
可行的临时规避思路
这些不是正式修复,只是降低伤害:
- 最终 completion 文本尽量短
- 把“写文件”和“对用户发消息”在逻辑上尽量分开
- 对特别关键的面向用户通知,暂时优先走更简单、更可控的投递路径
如果你的自动化已经面向客户或外部用户,这一轮最值得做的不是“再润色提示词”,而是审计哪些流程可能把内部运行摘要直接带出去。
结论
这份 issue 真正值得警惕的,不是 OpenClaw 无法完成后台任务,而是:本该只在运行时内部流动的 completion 上下文,可能穿透重写层,直接掉进用户聊天。
对生产环境来说,当前最务实的动作是三件事:
- 确认你自己的自动化链路是否受影响
- 收紧最终用户消息,减少可能泄漏的内部细节
- 收集可复现证据,帮助维护者加固 announce / completion 的共享边界
重新信任 completion announcement 前的发布闸门
如果你的自动化会把 completion announcement 投递给客户或外部用户,先把这篇当成上线前的高意图安全闸门。
- 渠道边界:确认同一个 completion 事件在你使用的每个渠道里都会被正确改写,不只是在 Web UI 里看起来正常。
- 原始元数据扫描:检查最终消息里是否出现 session id、task id、tool payload 名、文件路径、堆栈或路由说明。
- 失败样本对照:保留一份脱敏后的坏消息,以及一份期望投递的干净消息,方便维护者定位。
- 客户侧 fallback:提前定义 rewrite 层再次失效时,要走人工或单独审核的投递路径。
- 回归触发点:OpenClaw 升级、渠道插件升级、cron/subagent completion handler 改动后,都重新跑一次检查。
目标不是遮住某一个泄漏字段,而是证明内部 runtime context 在生产触发路径下不会绕过用户可见的 rewrite boundary。
如果你是从 troubleshooting 进来,先分清用户可见泄露和内部任务遥测
GA4 现在把这篇和 setup、troubleshooting、其他运维 bug 页放在同一组入口里。说明读者可能只是看到一条奇怪的 completion 消息,还没判断它是真的把 runtime 细节发给了用户,还是只出现在内部日志里。
删日志或改 announce 路径前,先按三类拆开:
- 消息已经到达用户可见渠道:先保留实际渲染文本、渠道、时间戳和触发任务,再改模板或转发逻辑。
- payload 只在内部日志里出现:先按可观测性噪音处理,再确认是否有 summarizer 或 bridge 会把它二次发到外部。
- completion event 要求发用户更新:必须改写成正常助手语气并去掉 runtime metadata,不要原样转发事件字段。
这样能让从高意图排障入口进来的读者,优先完成暴露面判断和安全交接,而不是做无效的大范围日志清理。
从 metadata leak 流量转成回复边界验收清单
如果你是因为 internal completion announce payload 把 raw runtime metadata 泄到用户回复里搜到这里,先不要只做字符串过滤。要把链路拆成三个边界:内部事件 payload 是否进入用户可见通道、completion renderer 是否区分系统字段和正文、以及异常 fallback 是否会把调试对象直接序列化。
最小验收清单包括:一条原始 announce payload、最终用户可见消息、renderer 字段白名单、以及异常路径下的脱敏输出样例。这样 metadata leak 流量会被引导到“消息边界、脱敏策略、回归测试”三类高意图入口,而不是停在一次泄漏截图。
来源
- Issue: openclaw/openclaw#61433
- 文档: Subagents
