fix(irc): sanitize internal tool-trace lines from outbound text#97214
Conversation
|
Codex review: needs maintainer review before merge. Reviewed June 27, 2026, 11:29 AM ET / 15:29 UTC. Summary PR surface: Source +268, Tests +1134, Docs +11, Other +12. Total +1425 across 39 files. Reproducibility: yes. Source inspection shows current main and v2026.6.10 only run IRC text through Review metrics: none identified. Stored data model Root-cause cluster Members:
Proposal only: this assessment does not dispatch repair, suppress jobs, mutate sibling items, close, or merge anything. Merge readiness Overall follows the weaker of proof and patch quality, so missing proof can cap an otherwise strong patch. Rank-up moves:
Risk before merge
Maintainer options:
Next step before merge
Security Review detailsBest possible solution: Land the narrow IRC adapter sanitizer hook and tests after maintainer acceptance, while keeping broader uncovered-channel coverage tracked in #90684. Do we have a high-confidence way to reproduce the issue? Yes. Source inspection shows current main and v2026.6.10 only run IRC text through Is this the best way to solve the issue? Yes. The PR fixes the channel-owned adapter hook that shared delivery already calls, reuses the existing SDK sanitizer, and matches merged Google Chat and Telegram sibling fixes instead of adding a new regex or config surface. AGENTS.md: found and applied where relevant. Codex review notes: model internal, reasoning high; reviewed against 4010b81a77f4. Label changesLabel justifications:
Evidence reviewedPR surface: Source +268, Tests +1134, Docs +11, Other +12. Total +1425 across 39 files. View PR surface stats
What I checked:
Likely related people:
What the crustacean ranks mean
Shiny media proof means a screenshot, video, or linked artifact directly shows the changed behavior. Runtime, network, CSP, and security claims still need visible diagnostics. How this review workflow works
|
|
Merged via squash.
|
…claw#97214) * fix(irc): sanitize internal tool-trace lines from outbound text * fix(irc): sanitize internal tool-trace lines from outbound text --------- Co-authored-by: Vincent Koc <[email protected]>
…penclaw#97360) Wrap the signal outbound sanitizeText hook with sanitizeAssistantVisibleText so assistant internal tool-trace scaffolding is stripped before delivery, matching the sibling channel fixes under openclaw#90684 (Telegram openclaw#95774, Google Chat openclaw#95084, IRC openclaw#97214).
…penclaw#97372) Wrap the matrix outbound sanitizeText hook with sanitizeAssistantVisibleText so assistant internal tool-trace scaffolding is stripped before delivery, matching the sibling channel fixes under openclaw#90684 (Telegram openclaw#95774, Google Chat openclaw#95084, IRC openclaw#97214). (cherry picked from commit 25490d4)
…claw#97214) * fix(irc): sanitize internal tool-trace lines from outbound text * fix(irc): sanitize internal tool-trace lines from outbound text --------- Co-authored-by: Vincent Koc <[email protected]>
…penclaw#97372) Wrap the matrix outbound sanitizeText hook with sanitizeAssistantVisibleText so assistant internal tool-trace scaffolding is stripped before delivery, matching the sibling channel fixes under openclaw#90684 (Telegram openclaw#95774, Google Chat openclaw#95084, IRC openclaw#97214).
…enclaw#97367) Wrap the slack outbound sanitizeText hook with sanitizeAssistantVisibleText so assistant internal tool-trace scaffolding is stripped before delivery, matching the sibling channel fixes under openclaw#90684 (Telegram openclaw#95774, Google Chat openclaw#95084, IRC openclaw#97214).
…penclaw#97360) Wrap the signal outbound sanitizeText hook with sanitizeAssistantVisibleText so assistant internal tool-trace scaffolding is stripped before delivery, matching the sibling channel fixes under openclaw#90684 (Telegram openclaw#95774, Google Chat openclaw#95084, IRC openclaw#97214).
…enclaw#97367) Wrap the slack outbound sanitizeText hook with sanitizeAssistantVisibleText so assistant internal tool-trace scaffolding is stripped before delivery, matching the sibling channel fixes under openclaw#90684 (Telegram openclaw#95774, Google Chat openclaw#95084, IRC openclaw#97214). (cherry picked from commit cd6d0f9)
…penclaw#97360) Wrap the signal outbound sanitizeText hook with sanitizeAssistantVisibleText so assistant internal tool-trace scaffolding is stripped before delivery, matching the sibling channel fixes under openclaw#90684 (Telegram openclaw#95774, Google Chat openclaw#95084, IRC openclaw#97214). (cherry picked from commit c026546)
…enclaw#97367) Wrap the slack outbound sanitizeText hook with sanitizeAssistantVisibleText so assistant internal tool-trace scaffolding is stripped before delivery, matching the sibling channel fixes under openclaw#90684 (Telegram openclaw#95774, Google Chat openclaw#95084, IRC openclaw#97214). (cherry picked from commit cd6d0f9)
…penclaw#97360) Wrap the signal outbound sanitizeText hook with sanitizeAssistantVisibleText so assistant internal tool-trace scaffolding is stripped before delivery, matching the sibling channel fixes under openclaw#90684 (Telegram openclaw#95774, Google Chat openclaw#95084, IRC openclaw#97214). (cherry picked from commit c026546)
…text The Nextcloud Talk outbound adapter had no sanitizeText hook, so internal assistant tool-trace scaffolding (e.g. "⚠️ 🛠️ `exec (agent)` failed", raw <tool_call>/<function_response> XML) leaked verbatim into delivered chat messages. The same one-line sanitizeText hook was already shipped to 13 sibling channels (mattermost openclaw#98693, feishu openclaw#98705, twitch openclaw#103109, signal openclaw#97360, slack openclaw#97367, matrix openclaw#97372, irc openclaw#97214, telegram, googlechat openclaw#90684, qqbot openclaw#90132, discord, whatsapp openclaw#71830, sms). Add sanitizeText: ({ text }) => sanitizeAssistantVisibleText(text) to the outbound base adapter, matching those precedents. Co-Authored-By: Claude <[email protected]>
The Nostr outbound adapter had no sanitizeText hook, so internal assistant tool-trace scaffolding (e.g. "⚠️ 🛠️ `exec (agent)` failed", raw <tool_call>/<function_response> XML) leaked verbatim into delivered Nostr DMs. The same one-line sanitizeText hook was already shipped to 13 sibling channels (twitch openclaw#103109, mattermost openclaw#98693, feishu openclaw#98705, signal openclaw#97360, slack openclaw#97367, matrix openclaw#97372, irc openclaw#97214, telegram, googlechat openclaw#90684, qqbot openclaw#90132, discord, whatsapp openclaw#71830, sms). Add sanitizeText to the NostrOutboundAdapter type and adapter, matching those precedents. Co-Authored-By: Claude <[email protected]>
The Zalo outbound adapter had no sanitizeText hook, so internal assistant tool-trace scaffolding (e.g. "⚠️ 🛠️ `exec (agent)` failed", raw <tool_call>/<function_response> XML) leaked verbatim into delivered Zalo messages. The same one-line sanitizeText hook was already shipped to 13 sibling channels (twitch openclaw#103109, mattermost openclaw#98693, feishu openclaw#98705, signal openclaw#97360, slack openclaw#97367, matrix openclaw#97372, irc openclaw#97214, telegram, googlechat openclaw#90684, qqbot openclaw#90132, discord, whatsapp openclaw#71830, sms). Add sanitizeText: ({ text }) => sanitizeAssistantVisibleText(text) to the outbound adapter, matching those precedents. Co-Authored-By: Claude <[email protected]>
The Nostr outbound adapter had no sanitizeText hook, so internal assistant tool-trace scaffolding (e.g. "⚠️ 🛠️ `exec (agent)` failed", raw <tool_call>/<function_response> XML) leaked verbatim into delivered Nostr DMs. The same one-line sanitizeText hook was already shipped to 13 sibling channels (twitch openclaw#103109, mattermost openclaw#98693, feishu openclaw#98705, signal openclaw#97360, slack openclaw#97367, matrix openclaw#97372, irc openclaw#97214, telegram, googlechat openclaw#90684, qqbot openclaw#90132, discord, whatsapp openclaw#71830, sms). Add sanitizeText to the NostrOutboundAdapter type and adapter, matching those precedents. Co-Authored-By: Claude <[email protected]>
The Zalo outbound adapter had no sanitizeText hook, so internal assistant tool-trace scaffolding (e.g. "⚠️ 🛠️ `exec (agent)` failed", raw <tool_call>/<function_response> XML) leaked verbatim into delivered Zalo messages. The same one-line sanitizeText hook was already shipped to 13 sibling channels (twitch openclaw#103109, mattermost openclaw#98693, feishu openclaw#98705, signal openclaw#97360, slack openclaw#97367, matrix openclaw#97372, irc openclaw#97214, telegram, googlechat openclaw#90684, qqbot openclaw#90132, discord, whatsapp openclaw#71830, sms). Add sanitizeText: ({ text }) => sanitizeAssistantVisibleText(text) to the outbound adapter, matching those precedents. Co-Authored-By: Claude <[email protected]>
The Zalo outbound adapter had no sanitizeText hook, so internal assistant tool-trace scaffolding (e.g. "⚠️ 🛠️ `exec (agent)` failed", raw <tool_call>/<function_response> XML) leaked verbatim into delivered Zalo messages. The same one-line sanitizeText hook was already shipped to 13 sibling channels (twitch openclaw#103109, mattermost openclaw#98693, feishu openclaw#98705, signal openclaw#97360, slack openclaw#97367, matrix openclaw#97372, irc openclaw#97214, telegram, googlechat openclaw#90684, qqbot openclaw#90132, discord, whatsapp openclaw#71830, sms). Add sanitizeText: ({ text }) => sanitizeAssistantVisibleText(text) to the outbound adapter, matching those precedents. Co-Authored-By: Claude <[email protected]>
The Nostr outbound adapter had no sanitizeText hook, so internal assistant tool-trace scaffolding (e.g. "⚠️ 🛠️ `exec (agent)` failed", raw <tool_call>/<function_response> XML) leaked verbatim into delivered Nostr DMs. The same one-line sanitizeText hook was already shipped to 13 sibling channels (twitch openclaw#103109, mattermost openclaw#98693, feishu openclaw#98705, signal openclaw#97360, slack openclaw#97367, matrix openclaw#97372, irc openclaw#97214, telegram, googlechat openclaw#90684, qqbot openclaw#90132, discord, whatsapp openclaw#71830, sms). Add sanitizeText to the NostrOutboundAdapter type and adapter, matching those precedents. Co-Authored-By: Claude <[email protected]>
The Nostr outbound adapter had no sanitizeText hook, so internal assistant tool-trace scaffolding (e.g. "⚠️ 🛠️ `exec (agent)` failed", raw <tool_call>/<function_response> XML) leaked verbatim into delivered Nostr DMs. The same one-line sanitizeText hook was already shipped to 13 sibling channels (twitch openclaw#103109, mattermost openclaw#98693, feishu openclaw#98705, signal openclaw#97360, slack openclaw#97367, matrix openclaw#97372, irc openclaw#97214, telegram, googlechat openclaw#90684, qqbot openclaw#90132, discord, whatsapp openclaw#71830, sms). Add sanitizeText to the NostrOutboundAdapter type and adapter, matching those precedents. Co-Authored-By: Claude <[email protected]>
The Zalo outbound adapter had no sanitizeText hook, so internal assistant tool-trace scaffolding (e.g. "⚠️ 🛠️ `exec (agent)` failed", raw <tool_call>/<function_response> XML) leaked verbatim into delivered Zalo messages. The same one-line sanitizeText hook was already shipped to 13 sibling channels (twitch openclaw#103109, mattermost openclaw#98693, feishu openclaw#98705, signal openclaw#97360, slack openclaw#97367, matrix openclaw#97372, irc openclaw#97214, telegram, googlechat openclaw#90684, qqbot openclaw#90132, discord, whatsapp openclaw#71830, sms). Add sanitizeText: ({ text }) => sanitizeAssistantVisibleText(text) to the outbound adapter, matching those precedents. Co-Authored-By: Claude <[email protected]>
The Zalo outbound adapter had no sanitizeText hook, so internal assistant tool-trace scaffolding (e.g. "⚠️ 🛠️ `exec (agent)` failed", raw <tool_call>/<function_response> XML) leaked verbatim into delivered Zalo messages. The same one-line sanitizeText hook was already shipped to 13 sibling channels (twitch openclaw#103109, mattermost openclaw#98693, feishu openclaw#98705, signal openclaw#97360, slack openclaw#97367, matrix openclaw#97372, irc openclaw#97214, telegram, googlechat openclaw#90684, qqbot openclaw#90132, discord, whatsapp openclaw#71830, sms). Add sanitizeText: ({ text }) => sanitizeAssistantVisibleText(text) to the outbound adapter, matching those precedents. Co-Authored-By: Claude <[email protected]>
…claw#97214) * fix(irc): sanitize internal tool-trace lines from outbound text * fix(irc): sanitize internal tool-trace lines from outbound text --------- Co-authored-by: Vincent Koc <[email protected]> (cherry picked from commit ddedf13)
…penclaw#97372) Wrap the matrix outbound sanitizeText hook with sanitizeAssistantVisibleText so assistant internal tool-trace scaffolding is stripped before delivery, matching the sibling channel fixes under openclaw#90684 (Telegram openclaw#95774, Google Chat openclaw#95084, IRC openclaw#97214). (cherry picked from commit 25490d4)
…enclaw#97367) Wrap the slack outbound sanitizeText hook with sanitizeAssistantVisibleText so assistant internal tool-trace scaffolding is stripped before delivery, matching the sibling channel fixes under openclaw#90684 (Telegram openclaw#95774, Google Chat openclaw#95084, IRC openclaw#97214). (cherry picked from commit cd6d0f9)
The Nostr outbound adapter had no sanitizeText hook, so internal assistant tool-trace scaffolding (e.g. "⚠️ 🛠️ `exec (agent)` failed", raw <tool_call>/<function_response> XML) leaked verbatim into delivered Nostr DMs. The same one-line sanitizeText hook was already shipped to 13 sibling channels (twitch openclaw#103109, mattermost openclaw#98693, feishu openclaw#98705, signal openclaw#97360, slack openclaw#97367, matrix openclaw#97372, irc openclaw#97214, telegram, googlechat openclaw#90684, qqbot openclaw#90132, discord, whatsapp openclaw#71830, sms). Add sanitizeText to the NostrOutboundAdapter type and adapter, matching those precedents. Co-Authored-By: Claude <[email protected]>
The Nostr outbound adapter had no sanitizeText hook, so internal assistant tool-trace scaffolding (e.g. "⚠️ 🛠️ `exec (agent)` failed", raw <tool_call>/<function_response> XML) leaked verbatim into delivered Nostr DMs. The same one-line sanitizeText hook was already shipped to 13 sibling channels (twitch openclaw#103109, mattermost openclaw#98693, feishu openclaw#98705, signal openclaw#97360, slack openclaw#97367, matrix openclaw#97372, irc openclaw#97214, telegram, googlechat openclaw#90684, qqbot openclaw#90132, discord, whatsapp openclaw#71830, sms). Add sanitizeText to the NostrOutboundAdapter type and adapter, matching those precedents. Co-Authored-By: Claude <[email protected]>
The Nostr outbound adapter had no sanitizeText hook, so internal assistant tool-trace scaffolding (e.g. "⚠️ 🛠️ `exec (agent)` failed", raw <tool_call>/<function_response> XML) leaked verbatim into delivered Nostr DMs. The same one-line sanitizeText hook was already shipped to 13 sibling channels (twitch openclaw#103109, mattermost openclaw#98693, feishu openclaw#98705, signal openclaw#97360, slack openclaw#97367, matrix openclaw#97372, irc openclaw#97214, telegram, googlechat openclaw#90684, qqbot openclaw#90132, discord, whatsapp openclaw#71830, sms). Add sanitizeText to the NostrOutboundAdapter type and adapter, matching those precedents. Co-Authored-By: Claude <[email protected]>
Related: #90684
What Problem This Solves
Fixes an issue where IRC users would see OpenClaw's internal tool-execution traces leak into channel messages. When a tool run fails, the runtime injects a status banner such as
⚠️ 🛠️ `…(agent)` failedinto the assistant's outbound text. On IRC — a plaintext-only transport — that banner was delivered verbatim instead of being stripped.Why This Change Was Made
The IRC outbound adapter's
sanitizeTextran onlysanitizeForPlainText(text), which does not strip assistant-visible scaffolding. The Telegram (#95774) and Google Chat (#95084) outbound adapters already wrap the same call withsanitizeAssistantVisibleText— the canonical assistant-visible sanitizer that removes tool-trace banners and other internal scaffolding (reasoning tags, tool-call XML). This change applies that same wrap to IRC: one import plussanitizeForPlainText(sanitizeAssistantVisibleText(text)), reusing the existing SDK sanitizer rather than adding a helper. The change is limited to the IRC adapter; other channels are tracked separately under #90684.User Impact
IRC users no longer see internal tool-trace banners — or other assistant-internal scaffolding handled by the shared sanitizer — in delivered messages. Ordinary assistant prose is unaffected.
Evidence
Focused unit tests —
extensions/irc/src/channel.test.tsadds 2 cases (tool-trace banner stripped; ordinary prose preserved):Real-behavior proof — the patched IRC outbound adapter's
ircOutboundBaseAdapter.sanitizeText, run directly against the real code path. No live IRC proof is included because the change is isolated to the outbound sanitizer; the command below exercises that adapter directly (the banner is runtime-injected, not model-produced, so a channel roundtrip adds no signal):Before the fix,
sanitizeForPlainText(text)alone leaks the banner verbatim; after the fix it is stripped toDone., and ordinary prose passes through unchanged.