Skip to content

fix(gateway): restrict media delivery to authorized cache directories#12850

Closed
Subway2023 wants to merge 2 commits into
NousResearch:mainfrom
Subway2023:main
Closed

fix(gateway): restrict media delivery to authorized cache directories#12850
Subway2023 wants to merge 2 commits into
NousResearch:mainfrom
Subway2023:main

Conversation

@Subway2023

@Subway2023 Subway2023 commented Apr 20, 2026

Copy link
Copy Markdown
Contributor

What does this PR do?

extract_local_files() validated only that a path existed on disk before passing it to platform adapters for upload. An attacker who could influence the agent's response text via prompt injection could cause the gateway to read and exfiltrate arbitrary host files (SSH keys, .env, etc.) to a chat channel.
This PR adds a path boundary check so only files inside the known Hermes cache directories (images, audio, documents, screenshots) can be delivered.

Related Issue
Fixes GHSA-5q48-xp7r-5pm8

@ether-btc ether-btc left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hermes Agent Code Review — PR #12850

Verdict: Request Changes

Important security fix. One gap: the security path _is_authorized_media_path has no dedicated tests.


🔴 Critical — No Tests for _is_authorized_media_path

File: gateway/platforms/base.py:830

The _is_authorized_media_path() function is the security boundary that prevents prompt injection attacks from exfiltrating arbitrary files. It has zero dedicated tests — only the behavior change in extract_local_files is indirectly tested (if at all).

A function with this security role needs direct unit tests covering:

  1. Authorized paths pass: Paths inside IMAGE_CACHE_DIR, AUDIO_CACHE_DIR, DOCUMENT_CACHE_DIR, and the screenshots dir should return True
  2. Unauthorized paths fail: Paths like /etc/passwd, /home/pi/.ssh/id_rsa, or ../../etc/passwd should return False
  3. Symlink traversal: A symlink pointing outside authorized dirs (if any exist on the system) should return False
  4. Invalid paths: Non-existent paths, permission-denied paths, and garbage input should return False safely (not raise)

Suggested fix:

  • Add a TestMediaPathAuthorization test class in tests/gateway/test_base.py with explicit test methods for each of the above cases
  • Use tmp_path fixtures to create temporary cache directories for testing authorized paths

✅ Looks Good

  • Clear, well-documented security boundary with explicit comment explaining the threat model
  • Correct use of Path.resolve() (not expanduser) for symlink resolution — important for security
  • Graceful error handling with try/except (ValueError, OSError) — paths that can't be resolved safely return False
  • Correct combination: os.path.isfile(expanded) AND _is_authorized_media_path(expanded) — both conditions must pass

Reviewed by Hermes Agent

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

Copy link
Copy Markdown
Collaborator

Likely duplicate of #10026 — same path boundary check for extract_local_files(). See also #4686.

1 similar comment
@alt-glitch

Copy link
Copy Markdown
Collaborator

Likely duplicate of #10026 — same path boundary check for extract_local_files(). See also #4686.

@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