Skip to content

Commit da3442c

Browse files
committed
fix(background): drop delivery exception detail from chat replies
/background show became reachable from a chat transport in this branch, and a chat gateway message is an external surface under the CWE-209 rule while the local terminal is not. The notify row rendered the persisted result verbatim, so a "failed: <reason>" outcome carried exception text to a surface that must not see it. Collapses that form to "failed" on the headless path only. The REPL table is untouched, and the curated "missing <channel> integration: ..." hints stay whole because they are the actionable half.
1 parent e011e0a commit da3442c

2 files changed

Lines changed: 26 additions & 1 deletion

File tree

gateway/tests/runtime/test_slash_routing.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -276,6 +276,25 @@ def test_gateway_background_show_returns_the_rca_as_plain_text() -> None:
276276
assert not _BOX_DRAWING & set(sink.finalized), sink.finalized
277277

278278

279+
def test_gateway_background_show_does_not_leak_delivery_exception_detail() -> None:
280+
task_id = _seed_record(
281+
task_id="bg-chat-redact",
282+
notification_results={
283+
"email": "failed: SMTPRecipientsRefused",
284+
"telegram": "sent",
285+
"buzz": "missing buzz integration: Buzz is not configured.",
286+
},
287+
)
288+
289+
sink = _run_gateway_slash(f"/background show {task_id}")
290+
291+
assert sink.finalized is not None
292+
assert "email:failed" in sink.finalized
293+
assert "SMTPRecipientsRefused" not in sink.finalized
294+
assert "telegram:sent" in sink.finalized
295+
assert "missing buzz integration: Buzz is not configured." in sink.finalized
296+
297+
279298
def test_gateway_background_list_is_plain_and_bounded() -> None:
280299
"""One line per record, and the root cause is trimmed. An unbounded list of
281300
twenty folded RCAs overruns the 4096-character message cap, and the transports

surfaces/interactive_shell/command_registry/background_cmds.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,10 @@ def _plain_list(records: dict[str, BackgroundInvestigationRecord]) -> str:
172172
return "\n".join(lines)
173173

174174

175+
def _chat_safe_outcome(outcome: str) -> str:
176+
return "failed" if outcome.startswith("failed:") else outcome
177+
178+
175179
def _plain_show(task_id: str, record: BackgroundInvestigationRecord) -> str:
176180
"""The same bounded sections the chat notification adapters already send."""
177181
from platform.notifications.rca_summary import summary_sections
@@ -190,7 +194,9 @@ def _plain_show(task_id: str, record: BackgroundInvestigationRecord) -> str:
190194
if next_steps:
191195
lines += ["", "What to do next:"] + [f" - {item}" for item in next_steps]
192196
if record.notification_results:
193-
delivered = ", ".join(f"{k}:{v}" for k, v in record.notification_results.items())
197+
delivered = ", ".join(
198+
f"{k}:{_chat_safe_outcome(v)}" for k, v in record.notification_results.items()
199+
)
194200
lines += ["", f"Notified: {delivered}"]
195201
return "\n".join(lines)
196202

0 commit comments

Comments
 (0)