Skip to content

[Bug]: Slack image attachments can be cached as HTML sign-in pages, causing downstream vision failures #6829

@frogGuaGuaGuaGua

Description

@frogGuaGuaGuaGua

Bug Description

Slack image attachments received through the gateway can be downloaded as a Slack HTML sign-in / redirect page and then cached locally with a .png/.jpg extension. Hermes later surfaces that cached path to the agent as if it were a real image, but vision_analyze eventually rejects it with Only real image files are supported for vision analysis.

This turns an upstream Slack media download/auth/access failure into a confusing downstream vision failure.

Steps to Reproduce

  1. Run Hermes with the Slack gateway enabled.
  2. In a Slack channel/thread where Hermes is active, mention the bot and attach an image.
  3. Ask Hermes to inspect/read the image (or rely on the normal image-analysis path).
  4. In failing cases, inspect the cached file under ~/.hermes/cache/images/ (or legacy ~/.hermes/image_cache/).
  5. Observe that the cached *.png/*.jpg file is actually HTML, and later vision_analyze fails.

Minimal evidence from a real repro:

$ file /Users/frog/.hermes/image_cache/img_244acf0cbbfe.png
/Users/frog/.hermes/image_cache/img_244acf0cbbfe.png: HTML document text, ASCII text, with very long lines (28115)

The cached file begins with <!DOCTYPE html> and has <title>Slack</title>.

Expected Behavior

If Slack media download fails or returns HTML / non-image bytes, Hermes should:

  • reject the download immediately,
  • log a clear Slack download/auth/access error,
  • avoid caching the response as an image,
  • and avoid handing the agent a bogus local image path.

Actual Behavior

Hermes caches arbitrary response bytes as an image file and only fails later, when vision_analyze performs magic-byte validation and returns:

Error analyzing image: Only real image files are supported for vision analysis.

Affected Component

  • Gateway (Telegram/Discord/Slack/WhatsApp)
  • Tools (terminal, file ops, web, code execution, etc.)

Messaging Platform (if gateway-related)

  • Slack

Operating System

macOS 13.7.8

Python Version

3.11.15

Hermes Version

v0.8.0 (2026.4.8)

Relevant Logs / Traceback

vision_analyze -> Error analyzing image: Only real image files are supported for vision analysis.

$ file /Users/frog/.hermes/image_cache/img_244acf0cbbfe.png
HTML document text, ASCII text, with very long lines (28115)

Root Cause Analysis (optional)

Current Slack image handling appears to accept the response body as image bytes without validating that it is actually an image:

  • gateway/platforms/slack.py:874-882 routes Slack image/* attachments into _download_slack_file(...)
  • gateway/platforms/slack.py:1299-1321 performs an authenticated GET and then immediately calls cache_image_from_bytes(response.content, ext)
  • gateway/platforms/base.py:95-110 blindly writes those bytes to disk
  • tools/vision_tools.py:102-121 and 355-357 later detect that the cached file is not a real image and reject it

So even if the underlying trigger is Slack auth/scope/access/redirect behavior, Hermes currently converts that upstream failure into a misleading downstream vision error instead of failing at the Slack download boundary.

Related external reports show the same Slack symptom (HTML sign-in page instead of file bytes):

Proposed Fix (optional)

  1. Validate Slack download responses before caching them as images.
    • Reject text/html responses.
    • Also validate image magic bytes (not just extension / Slack metadata) before cache_image_from_bytes(...).
  2. Return/log an explicit Slack media download error when the response is HTML or otherwise not an image.
  3. Add a regression test that simulates 200 OK + HTML body from a Slack file URL and asserts Hermes does not cache it as an image.

There are already retry-path tests for Slack media download, but I did not find a regression test for the HTTP 200 but body is HTML login page case.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    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