Skip to content

fix(security): validate media file paths to prevent arbitrary file read [HIGH]#4686

Closed
Joshua-Medvinsky wants to merge 1 commit into
NousResearch:mainfrom
Joshua-Medvinsky:fix/media-path-validation
Closed

fix(security): validate media file paths to prevent arbitrary file read [HIGH]#4686
Joshua-Medvinsky wants to merge 1 commit into
NousResearch:mainfrom
Joshua-Medvinsky:fix/media-path-validation

Conversation

@Joshua-Medvinsky

Copy link
Copy Markdown

Security Finding: Arbitrary File Read via LLM Media Tag Injection

Severity: HIGH
Reported by: FailSafe Security Researcher
Component: gateway/platforms/base.pyextract_media()

Description

extract_media() parses MEDIA:<path> tags from LLM response text and passes extracted paths directly to platform send methods (send_image_file, send_voice, send_video, send_document) without validating that the path resides within an allowed directory. The regex includes a \S+ catch-all that accepts any non-whitespace path, including absolute paths like /etc/passwd.

An indirect prompt injection (via poisoned web content, malicious document, or injected tool output) can cause the LLM to emit a MEDIA: tag referencing a sensitive file. The file is read and sent to the chat with no validation.

Fix

Add _is_safe_media_path() which resolves the path and verifies it resides within ~/.hermes/media_cache before allowing delivery. Paths outside the cache directory are silently dropped.

Test plan

  • Verify TTS/media tool outputs still work (paths within media cache)
  • Verify MEDIA:/etc/passwd is rejected (path outside cache)
  • Verify MEDIA:../../etc/shadow is rejected (traversal)

…ad [HIGH]

Previously, `extract_media()` parsed MEDIA:<path> tags from LLM responses
and passed extracted paths directly to platform send methods without any
validation. A prompt injection attack could cause the LLM to emit
MEDIA:/etc/passwd or similar, exfiltrating any file readable by the
process.

Add `_is_safe_media_path()` which resolves the path and verifies it
resides within ~/.hermes/media_cache before allowing delivery. Paths
outside the cache directory are silently dropped.

Reported-by: FailSafe Security Researcher
Co-Authored-By: Joshua Medvinsky <joshua-medvinsky@users.noreply.github.com>
@Joshua-Medvinsky

Copy link
Copy Markdown
Author

Hey @erosika @teknium1 — flagging for review. This is a security fix for an arbitrary file read vulnerability in the media tag parser. Happy to discuss if you have questions.

@alt-glitch alt-glitch added type/security Security vulnerability or hardening P0 Critical — data loss, security, crash loop comp/gateway Gateway runner, session dispatch, delivery labels May 1, 2026
@alt-glitch

Copy link
Copy Markdown
Collaborator

Likely duplicate of #10026 and #16547 — same MEDIA path traversal vulnerability in extract_media(). Multiple PRs addressing same CWE-22 issue.

1 similar comment
@alt-glitch

Copy link
Copy Markdown
Collaborator

Likely duplicate of #10026 and #16547 — same MEDIA path traversal vulnerability in extract_media(). Multiple PRs addressing same CWE-22 issue.

Cyrene963 pushed a commit to Cyrene963/hermes-agent that referenced this pull request May 7, 2026
The static method _is_safe_media_path() was called without the
BasePlatformAdapter class prefix inside another @staticmethod
(extract_media). This caused NameError when the CLI's send_message
tool tried to send files via MEDIA: tags, breaking file delivery
from CLI sessions.

Gateway file sending worked because it uses send_document() directly,
bypassing extract_media().

Fix: _is_safe_media_path(path) → BasePlatformAdapter._is_safe_media_path(path)

Introduced by PR NousResearch#4686 (security: validate media file paths) where
the conflict resolution dropped the class prefix.
@teknium1

Copy link
Copy Markdown
Contributor

Superseded by PR #30432 (merged 41d2c75, credit @egilewski). The merged fix covers all MEDIA delivery sites (not just extract_media in one adapter), resolves symlinks before containment checks, and ships with regression coverage across cron, gateway, weixin, send_message, and yuanbao. Thanks for catching this class early — the four parallel PRs on this issue were what told us this was a real defense gap worth landing.

@teknium1 teknium1 closed this May 23, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

comp/gateway Gateway runner, session dispatch, delivery P0 Critical — data loss, security, crash loop type/security Security vulnerability or hardening

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants