fix: escape command content in Telegram exec approval prompt

Switch from fragile Markdown V1 to HTML parse mode with html.escape()
for exec approval messages. Add fallback to text-based approval when
the formatted send fails.

Cherry-picked from #10999 by @danieldoderlein.
This commit is contained in:
danieldoderlein 2026-04-16 19:22:30 +05:30 committed by kshitij
parent 8c1276c0bf
commit 31a72bdbf2
2 changed files with 12 additions and 9 deletions

View file

@ -11,6 +11,7 @@ import asyncio
import json
import logging
import os
import html as _html
import re
from typing import Dict, List, Optional, Any
@ -1129,13 +1130,10 @@ class TelegramAdapter(BasePlatformAdapter):
try:
cmd_preview = command[:3800] + "..." if len(command) > 3800 else command
# Escape backticks that would break Markdown v1 inline code parsing
safe_cmd = cmd_preview.replace("`", "'")
safe_desc = description.replace("`", "'").replace("*", "")
text = (
f"⚠️ *Command Approval Required*\n\n"
f"`{safe_cmd}`\n\n"
f"Reason: {safe_desc}"
f"⚠️ <b>Command Approval Required</b>\n\n"
f"<pre>{_html.escape(cmd_preview)}</pre>\n\n"
f"Reason: {_html.escape(description)}"
)
# Resolve thread context for thread replies
@ -1163,7 +1161,7 @@ class TelegramAdapter(BasePlatformAdapter):
kwargs: Dict[str, Any] = {
"chat_id": int(chat_id),
"text": text,
"parse_mode": ParseMode.MARKDOWN,
"parse_mode": ParseMode.HTML,
"reply_markup": keyboard,
**self._link_preview_kwargs(),
}

View file

@ -8816,7 +8816,7 @@ class GatewayRunner:
# false positives from MagicMock auto-attribute creation in tests.
if getattr(type(_status_adapter), "send_exec_approval", None) is not None:
try:
asyncio.run_coroutine_threadsafe(
_approval_result = asyncio.run_coroutine_threadsafe(
_status_adapter.send_exec_approval(
chat_id=_status_chat_id,
command=cmd,
@ -8826,7 +8826,12 @@ class GatewayRunner:
),
_loop_for_step,
).result(timeout=15)
return
if _approval_result.success:
return
logger.warning(
"Button-based approval failed (send returned error), falling back to text: %s",
_approval_result.error,
)
except Exception as _e:
logger.warning(
"Button-based approval failed, falling back to text: %s", _e