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:
@@ -11,6 +11,7 @@ import asyncio
|
|||||||
import json
|
import json
|
||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
|
import html as _html
|
||||||
import re
|
import re
|
||||||
from typing import Dict, List, Optional, Any
|
from typing import Dict, List, Optional, Any
|
||||||
|
|
||||||
@@ -1129,13 +1130,10 @@ class TelegramAdapter(BasePlatformAdapter):
|
|||||||
|
|
||||||
try:
|
try:
|
||||||
cmd_preview = command[:3800] + "..." if len(command) > 3800 else command
|
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 = (
|
text = (
|
||||||
f"⚠️ *Command Approval Required*\n\n"
|
f"⚠️ <b>Command Approval Required</b>\n\n"
|
||||||
f"`{safe_cmd}`\n\n"
|
f"<pre>{_html.escape(cmd_preview)}</pre>\n\n"
|
||||||
f"Reason: {safe_desc}"
|
f"Reason: {_html.escape(description)}"
|
||||||
)
|
)
|
||||||
|
|
||||||
# Resolve thread context for thread replies
|
# Resolve thread context for thread replies
|
||||||
@@ -1163,7 +1161,7 @@ class TelegramAdapter(BasePlatformAdapter):
|
|||||||
kwargs: Dict[str, Any] = {
|
kwargs: Dict[str, Any] = {
|
||||||
"chat_id": int(chat_id),
|
"chat_id": int(chat_id),
|
||||||
"text": text,
|
"text": text,
|
||||||
"parse_mode": ParseMode.MARKDOWN,
|
"parse_mode": ParseMode.HTML,
|
||||||
"reply_markup": keyboard,
|
"reply_markup": keyboard,
|
||||||
**self._link_preview_kwargs(),
|
**self._link_preview_kwargs(),
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8816,7 +8816,7 @@ class GatewayRunner:
|
|||||||
# false positives from MagicMock auto-attribute creation in tests.
|
# false positives from MagicMock auto-attribute creation in tests.
|
||||||
if getattr(type(_status_adapter), "send_exec_approval", None) is not None:
|
if getattr(type(_status_adapter), "send_exec_approval", None) is not None:
|
||||||
try:
|
try:
|
||||||
asyncio.run_coroutine_threadsafe(
|
_approval_result = asyncio.run_coroutine_threadsafe(
|
||||||
_status_adapter.send_exec_approval(
|
_status_adapter.send_exec_approval(
|
||||||
chat_id=_status_chat_id,
|
chat_id=_status_chat_id,
|
||||||
command=cmd,
|
command=cmd,
|
||||||
@@ -8826,7 +8826,12 @@ class GatewayRunner:
|
|||||||
),
|
),
|
||||||
_loop_for_step,
|
_loop_for_step,
|
||||||
).result(timeout=15)
|
).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:
|
except Exception as _e:
|
||||||
logger.warning(
|
logger.warning(
|
||||||
"Button-based approval failed, falling back to text: %s", _e
|
"Button-based approval failed, falling back to text: %s", _e
|
||||||
|
|||||||
Reference in New Issue
Block a user