fix(slack): sanitize internal tool-trace lines from outbound text#97367
Conversation
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).
|
Codex review: needs maintainer review before merge. Reviewed June 28, 2026, 1:22 AM ET / 05:22 UTC. Summary PR surface: Source +2, Tests +19. Total +21 across 2 files. Reproducibility: yes. source-reproducible: current main and v2026.6.10 lack Slack's sanitizeText hook, while shared delivery only calls assistant-visible sanitization when a channel supplies that hook. I did not run a live Slack roundtrip in this read-only review. Review metrics: 1 noteworthy metric.
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:
Mantis proof suggestion Risk before merge
Maintainer options:
Next step before merge
Security Review detailsBest possible solution: Land the focused Slack outbound hook after required checks if maintainers accept the canonical sanitizer semantics, while keeping remaining uncovered channels tracked by #90684. Do we have a high-confidence way to reproduce the issue? Yes, source-reproducible: current main and v2026.6.10 lack Slack's sanitizeText hook, while shared delivery only calls assistant-visible sanitization when a channel supplies that hook. I did not run a live Slack roundtrip in this read-only review. Is this the best way to solve the issue? Yes, this is the best bounded fix for the Slack slice because it wires the existing SDK sanitizer at the Slack plugin outbound boundary instead of adding new regexes or downstream send-path special cases. A future shared global sanitizer remains a broader maintainer choice for the umbrella issue. AGENTS.md: found and applied where relevant. Codex review notes: model internal, reasoning high; reviewed against 69af58ba2613. Label changesLabel changes:
Label justifications:
Evidence reviewedPR surface: Source +2, Tests +19. Total +21 across 2 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
|
…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).
…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).
…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).
…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).
…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)
…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)
…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]>
…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 OpenClaw's internal tool-execution traces could leak into Slack outbound messages. When a tool run fails, the runtime injects a status banner such as
⚠️ 🛠️ `…(agent)` failedinto the assistant's outbound text. Slack's outbound adapter defined nosanitizeTexthook, so the only sanitization that ran was core's centralstripInternalRuntimeScaffoldingFromPayload— which removes runtime-injected context wrappers (<system-reminder>, etc.) but not these tool-trace lines. The banner was therefore delivered verbatim.Why This Change Was Made
The merged Telegram (PR #95774), Google Chat (PR #95084), and IRC (PR #97214) changes already wrap their outbound text with
sanitizeAssistantVisibleText— the existing shared assistant-visible sanitizer that removes tool-trace banners and other internal scaffolding (reasoning tags, tool-call XML) while preserving ordinary prose and formatting. Slack was a missed sibling of that same fix, tracked under #90684. This change adds the same hook to the Slack outbound adapter (one import plussanitizeText: ({ text }) => sanitizeAssistantVisibleText(text)), reusing the existing SDK sanitizer rather than adding a helper. It appliessanitizeAssistantVisibleTextdirectly (not the IRC-stylesanitizeForPlainTextwrap) so Slack's mrkdwn rendering is untouched. The hook sanitizes the assistant reply text (payload.text), which is the leak surface. The change touches onlyextensions/slack/src/channel.ts(the outbound adapter) plus a focused test; other channels are tracked separately under #90684.User Impact
Slack outbound messages no longer include internal tool-trace banners; the shared sanitizer also strips its other inherited internal scaffolding (reasoning tags, tool-call XML). Ordinary assistant prose is unaffected.
Evidence
Focused unit tests —
extensions/slack/src/outbound-tool-trace-sanitize.test.tsadds 2 cases (tool-trace banner stripped; ordinary prose preserved):Real-behavior proof — the patched
slackPlugin.outbound.sanitizeText, run directly against the real plugin code path. No live Slack roundtrip is included: this PR only wires the existing outbound sanitizer hook, and the command below exercises that changed code path directly:Before this change Slack defined no
sanitizeTexthook, so the banner reached users verbatim.