fix(gateway): deliver $HOME deliverables on root-run gateways
Root-run gateways have $HOME=/root, which is on the MEDIA system-path denylist, so the gateway silently dropped agent-generated deliverables under /root (e.g. /root/work/proposal.docx) — the user got a 'here is your file' reply with nothing attached. _path_under_denied_prefix now treats the running user's own home as deliverable: the home tree itself is no longer denied, while the more-specific denied paths inside it (~/.ssh, ~/.aws, ~/.hermes/.env, auth.json, config.yaml) stay blocked because they are separate denylist entries. The exception only matches when the denied prefix IS $HOME, so a non-root gateway still can't deliver another user's home. Diagnosis, reproduction, and the failing-case analysis are from @GodsBoy (#38108 / #38106). Implemented here as the minimal denylist fix rather than a staging/copy subsystem. Co-authored-by: GodsBoy <dhuysamen@gmail.com>
This commit is contained in:
committed by
Teknium
co-authored by
GodsBoy
parent
580d924097
commit
2982122be7
@@ -967,14 +967,35 @@ def _media_delivery_denied_paths() -> List[Path]:
|
||||
|
||||
|
||||
def _path_under_denied_prefix(resolved: Path) -> bool:
|
||||
"""Return True if ``resolved`` lives under a deny-listed system path."""
|
||||
"""Return True if ``resolved`` lives under a deny-listed system path.
|
||||
|
||||
One narrow exception: when a denied prefix IS the running user's own home,
|
||||
the home itself is not treated as denied. ``/root`` is on the system-path
|
||||
denylist so that a non-root gateway can't deliver another user's home, but
|
||||
on a root-run gateway ``$HOME=/root`` and the operator's own deliverables
|
||||
(``/root/work/proposal.docx``) live directly under it. The credential
|
||||
sub-directories inside home (``~/.ssh``, ``~/.aws``, ...) and Hermes
|
||||
secrets (``~/.hermes/.env``, ``auth.json``) are *separate, more-specific*
|
||||
denied paths, so they stay blocked regardless of this exception — it can
|
||||
only un-block a plain file sitting in the running user's home tree, never a
|
||||
credential location or another user's home.
|
||||
"""
|
||||
try:
|
||||
home = Path(os.path.expanduser("~")).resolve(strict=False)
|
||||
except (OSError, RuntimeError, ValueError):
|
||||
home = None
|
||||
for denied in _media_delivery_denied_paths():
|
||||
try:
|
||||
resolved_denied = denied.expanduser().resolve(strict=False)
|
||||
except (OSError, RuntimeError, ValueError):
|
||||
continue
|
||||
if _path_is_within(resolved, resolved_denied) or resolved == resolved_denied:
|
||||
return True
|
||||
if not (_path_is_within(resolved, resolved_denied) or resolved == resolved_denied):
|
||||
continue
|
||||
# Allow the running user's own home tree; its credential sub-dirs are
|
||||
# caught by their own (more-specific) denylist entries above.
|
||||
if home is not None and resolved_denied == home:
|
||||
continue
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user