[security] fix(gateway): contain MEDIA directive file delivery#16547
[security] fix(gateway): contain MEDIA directive file delivery#16547Hinotoi-agent wants to merge 5 commits into
Conversation
a6459a7 to
1303ac9
Compare
|
Rebased onto current Current head: The only rebase conflict was in Validation after rebase:
|
1303ac9 to
601689d
Compare
|
Rebased onto upstream main and resolved the gateway MEDIA directive test conflict. New head: 601689d03a63a63797f531d957afa7be500491b7. Local validation: |
|
Pushed Root cause:
Local validation: Note: |
6ebe65a to
aa6e0d2
Compare
|
Pushed follow-up What changed:
Local validation: GitHub Actions after the push are now passing, including the previously failing |
6a34df4 to
1812538
Compare
e210e63 to
498d0cc
Compare
|
Superseded by PR #30432 (merged 41d2c75, credit @egilewski). The merged fix covers all MEDIA delivery sites (not just |
Summary
This PR hardens the gateway
MEDIA[:]<path>attachment path against model-controlled local-file exfiltration by requiring every extracted media directive to resolve to an existing regular file under a Hermes-managed media cache root, or under an operator-configured allowlist root.The current gateway treats assistant output as an attachment instruction: if a response contains the media-delivery prefix followed by an absolute local path, the platform adapter extracts that path and later sends the referenced local file through Telegram/Discord/Slack/etc. Because assistant text can be influenced by untrusted prompts, arbitrary host paths should not become sendable attachments.
Security issues covered
MEDIA[:]directives can cause native gateway delivery of arbitrary local files, including sensitive extensionless host filesBefore this PR
BasePlatformAdapter.extract_media()accepted absoluteMEDIA[:]paths after simple parsing and~expansion.After this PR
MEDIA[:]paths are validated withBasePlatformAdapter.validate_media_delivery_path()before they are returned for attachment delivery.~expansion;HERMES_MEDIA_ALLOW_DIRSwhen they intentionally want a local directory to be deliverable.Why this matters
Gateway
MEDIA[:]tags are a protocol boundary between model text and host file I/O. If the model can be induced to emit a local path, the gateway may upload that file to the user's messaging platform. That creates a high-impact confidentiality risk for any secrets, transcripts, logs, screenshots, exports, or other host files with supported extensions.The safe default is that only files created or cached for Hermes media delivery should be attachable. Arbitrary local paths should remain text unless the operator explicitly marks a directory as deliverable.
Verified live behavior
During validation on a live Telegram-backed Hermes gateway, a response that contained the media-delivery prefix followed by
/etc/passwdcaused the gateway to upload the local/etc/passwdfile into Telegram. This was not just visible text in the message body; the platform delivery layer treated the assistant output as an attachment instruction and sent the referenced host file.This happened because the gateway parsed assistant text after generation, extracted the local path from the directive-like output, and handed that path to the Telegram adapter for native file delivery without first enforcing a host-file containment boundary. Markdown/code-fence formatting did not provide a security boundary because parsing happens on the outgoing response text rather than on a trusted structured tool result.
/etc/passwdis used here only as a reproducible low-risk system-account metadata file. It should still never be deliverable from model-controlled text, and the same behavior would be more serious for secrets, logs, screenshots, transcripts, exported documents, or other readable host files.How this differs from #6084
This PR is in the same public security family as #6084, but it fixes a stricter boundary.
MEDIA[:]values are local absolute paths with known media extensions.Both approaches reduce risk, but containment is the security boundary that prevents arbitrary host file reads/uploads through model-emitted attachment directives.
Attack flow
Affected code
gateway/platforms/base.pyBasePlatformAdapter.extract_media()parsed model-emittedMEDIA[:]tags into local pathsgateway/platforms/base.pytests/gateway/test_platform_base.pyRoot cause
MEDIA[:]files to Hermes-generated/cache-managed outputs.CVSS assessment
MEDIA[:]local-file exfiltration via model-controlled attachment directivesCVSS:3.1/AV:N/AC:L/PR:L/UI:R/S:C/C:H/I:N/A:NRationale: an attacker generally needs a way to influence assistant output or conversation context, and the gateway user/session must receive the crafted response. If successful, the impact crosses from model text into host file disclosure through a messaging platform attachment, with high confidentiality impact and no direct integrity or availability impact claimed here.
Safe reproduction steps
A safe regression shape is included in the tests:
outside-secret.png.MEDIA[:]<outside-file>in gateway response text.MEDIA[:]<safe-root-symlink>.Expected vulnerable behavior
On vulnerable code,
extract_media()returns expanded absolute paths directly from the assistant response. AMEDIA[:]directive that names a readable local file with a supported extension can be passed to the platform delivery path without proving the file came from a Hermes media cache or operator-approved root.Changes in this PR
MEDIA_DELIVERY_SAFE_ROOTSfor Hermes-managed media/document/screenshot cache directories.HERMES_MEDIA_ALLOW_DIRSfor explicit operator opt-in roots.validate_media_delivery_path()to require absolute, existing, regular files.extract_media()to return only validated media paths.Files changed
gateway/platforms/base.pytests/gateway/test_platform_base.pyMaintainer impact
MEDIA[:]tags are left as plain text instead of being silently converted into attachments.HERMES_MEDIA_ALLOW_DIRSto opt in specific directories.MEDIA[:]support; it narrows the local-file delivery boundary.Fix rationale
The gateway should authorize file delivery based on where the file came from, not on whether model text contains a plausible file extension. Containing attachment delivery to Hermes media caches preserves intended generated-media behavior while preventing prompt-influenced arbitrary host file disclosure.
Type of change
Test plan
Commands run locally:
Results:
Note:
gateway/platforms/base.pycurrently has pre-existingE402import-order findings in this repository layout, so the targeted ruff command ignoresE402and checks the security-relevant changes plus the updated tests.Disclosure notes
This PR is intentionally bounded to the gateway
MEDIA[:]directive local-file delivery boundary. It does not claim to address every possible prompt-injection path, every gateway attachment path, or every local file reference feature. It specifically prevents model-emittedMEDIA[:]attachment directives from reading and sending arbitrary host files unless those files are under Hermes-managed media caches or explicitly operator-allowlisted directories.