Bug Description
The send_message tool's _send_telegram() function (line 813 of tools/send_message_tool.py) delivers media files directly via bot.send_document() without calling validate_media_delivery_path(). This bypasses the MEDIA_DELIVERY_SAFE_ROOTS allowlist that the gateway's response delivery pipeline enforces.
Impact
- Single-user (local): Low risk — the user controls their own files
- Multi-user / public gateway: Medium risk — a prompt injection attack could instruct the agent to use
send_message with MEDIA: tags pointing to sensitive files (e.g., ~/.ssh/id_rsa, ~/.aws/credentials) and exfiltrate them to a chat controlled by the attacker
- Severity: P2 — security bypass with workaround (don't run public gateways)
Reproduction
- Have the agent call
send_message(message="MEDIA:/etc/hosts", target="telegram")
- The file is delivered as a document attachment despite
/etc/ not being in MEDIA_DELIVERY_SAFE_ROOTS
- Compare with the gateway response pipeline which correctly logs:
"Skipping unsafe MEDIA directive path outside allowed roots"
Root Cause
In tools/send_message_tool.py, the flow is:
# Line 253 — extract_media does parse MEDIA: tags ✅
media_files, cleaned_message = BasePlatformAdapter.extract_media(message)
# Line 254 — filter_media_delivery_paths is called
media_files = BasePlatformAdapter.filter_media_delivery_paths(media_files)
# Line 304-310 — passed to _send_to_platform → _send_telegram
# _send_telegram opens and sends the file directly via bot.send_document()
# WITHOUT calling validate_media_delivery_path()
The gateway's response pipeline (base.py:3642) calls filter_media_delivery_paths → validate_media_delivery_path which checks the allowlist. But _send_telegram() (line 946-977) only checks os.path.exists() — it never validates against allowed roots.
Suggested Fix
Add a validate_media_delivery_path() check in _send_telegram() before opening the file:
# In _send_telegram(), around line 946:
for media_path, is_voice in media_files:
if not os.path.exists(media_path):
warning = f"Media file not found, skipping: {media_path}"
logger.warning(warning)
warnings.append(warning)
continue
# ADD: validate against safe roots
from gateway.platforms.base import validate_media_delivery_path
if not validate_media_delivery_path(media_path):
warning = f"Skipping unsafe media path outside allowed roots: {media_path}"
logger.warning(warning)
warnings.append(warning)
continue
ext = os.path.splitext(media_path)[1].lower()
# ... rest of send logic
Additional Finding
The MEDIA: regex in base.py:2461 does not support .md files (extension not in the pattern). Consider adding md to the extension list.
Environment
- Hermes v0.15.0
- macOS 26.5
- Platform: Telegram
Related
Bug Description
The
send_messagetool's_send_telegram()function (line 813 oftools/send_message_tool.py) delivers media files directly viabot.send_document()without callingvalidate_media_delivery_path(). This bypasses theMEDIA_DELIVERY_SAFE_ROOTSallowlist that the gateway's response delivery pipeline enforces.Impact
send_messagewithMEDIA:tags pointing to sensitive files (e.g.,~/.ssh/id_rsa,~/.aws/credentials) and exfiltrate them to a chat controlled by the attackerReproduction
send_message(message="MEDIA:/etc/hosts", target="telegram")/etc/not being inMEDIA_DELIVERY_SAFE_ROOTS"Skipping unsafe MEDIA directive path outside allowed roots"Root Cause
In
tools/send_message_tool.py, the flow is:The gateway's response pipeline (
base.py:3642) callsfilter_media_delivery_paths→validate_media_delivery_pathwhich checks the allowlist. But_send_telegram()(line 946-977) only checksos.path.exists()— it never validates against allowed roots.Suggested Fix
Add a
validate_media_delivery_path()check in_send_telegram()before opening the file:Additional Finding
The
MEDIA:regex inbase.py:2461does not support.mdfiles (extension not in the pattern). Consider addingmdto the extension list.Environment
Related
validate_media_delivery_pathand the safe-roots allowlist