Skip to content

Bug: send_message tool bypasses validate_media_delivery_path security check #34270

@yadomichen

Description

@yadomichen

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

  1. Have the agent call send_message(message="MEDIA:/etc/hosts", target="telegram")
  2. The file is delivered as a document attachment despite /etc/ not being in MEDIA_DELIVERY_SAFE_ROOTS
  3. 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_pathsvalidate_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

Metadata

Metadata

Assignees

No one assigned

    Labels

    P2Medium — degraded but workaround existscomp/gatewayGateway runner, session dispatch, deliverycomp/toolsTool registry, model_tools, toolsetstype/securitySecurity vulnerability or hardening

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions