mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-05-29 06:31:32 +00:00
fix(gateway): allow native delivery of freshly-produced agent files (#32060)
The gateway's media delivery allowlist required files live inside
`~/.hermes/cache/{documents,images,...}`, which is the wrong shape for
real agent usage. Agents naturally produce artifacts via terminal tools
(`pandoc -o /tmp/report.pdf`, `matplotlib savefig`, etc.) or
write_file into project directories — these never land under the cache.
Result: users got a raw file path in chat instead of an attachment.
This is doubly bad in deployment shapes where the cache directories
aren't writable by the agent at all: Hermes running in Docker with a
read-only mount, or with a Docker/Modal/SSH terminal backend whose
filesystem isn't the gateway host's filesystem.
Layered trust model:
1. Cache-dir allowlist (unchanged) — Hermes-managed roots always trusted.
2. Operator allowlist — `HERMES_MEDIA_ALLOW_DIRS` env var, now also
surfaced as `gateway.media_delivery_allow_dirs` in config.yaml.
3. Recency-based trust (new, default on) — files whose mtime is within
`gateway.trust_recent_files_seconds` (default 600s) of "now" are
trusted even outside the cache/operator allowlist. Old host files
(`/etc/passwd`, `~/.bashrc`, `~/.ssh/id_rsa`) have mtimes measured
in days/months, well outside the window — prompt-injection paths
pointing at pre-existing files are still rejected.
4. Hard denylist — `/etc`, `/proc`, `/sys`, `/dev`, `/root`, `/boot`,
`/var/{log,lib,run}`, plus `$HOME/.{ssh,aws,gnupg,kube,docker,config,
azure,gcloud}` and `Library/Keychains`. Denylist blocks delivery
even when recency would trust the file, in case an attacker
somehow refreshes a sensitive file's mtime.
Operators who want strict-allowlist behavior set
`gateway.trust_recent_files: false` and the system reverts to
pre-existing behavior.
Tests: 6 new cases in test_platform_base.py cover the recency window,
disabled mode, system-path denylist, and the motivating PDF-in-project
scenario. 3 existing tests (test_platform_base, test_tts_media_routing,
test_send_message_tool) that exercised the strict-allowlist path are
updated to disable recency trust explicitly.
E2E validation: real `validate_media_delivery_path()` accepts fresh
PDFs in /tmp and project dirs, rejects /etc/passwd, ~/.ssh/id_rsa, and
files older than the window; config.yaml `gateway.*` keys bridge
correctly to the env vars the validator reads.
This commit is contained in:
parent
0ff7c09e2f
commit
a989a79c0c
6 changed files with 279 additions and 1 deletions
|
|
@ -377,7 +377,11 @@ class TestSendMessageTool:
|
|||
user_id="user-123",
|
||||
)
|
||||
|
||||
def test_media_tag_outside_allowed_roots_is_not_sent(self, tmp_path):
|
||||
def test_media_tag_outside_allowed_roots_is_not_sent(self, tmp_path, monkeypatch):
|
||||
# This test exercises the strict-allowlist path; disable recency trust
|
||||
# so the freshly-written tmp_path file is not auto-accepted by the
|
||||
# trust window. (Recency trust is covered in test_platform_base.py.)
|
||||
monkeypatch.setenv("HERMES_MEDIA_TRUST_RECENT_FILES", "0")
|
||||
config, telegram_cfg = _make_config()
|
||||
secret = tmp_path / "secret.pdf"
|
||||
secret.write_bytes(b"%PDF secret")
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue