fix(ssh): keep bulk sync extraction scoped to .hermes

This commit is contained in:
Stark-X 2026-05-11 16:39:52 +08:00 committed by Teknium
parent 4a2fa77c15
commit eb51fb6f50
2 changed files with 47 additions and 8 deletions

View file

@ -169,6 +169,7 @@ class SSHEnvironment(BaseEnvironment):
if not files:
return
base = f"{self._remote_home}/.hermes"
parents = unique_parent_dirs(files)
if parents:
cmd = self._build_ssh_command()
@ -180,7 +181,19 @@ class SSHEnvironment(BaseEnvironment):
# Symlink staging avoids fragile GNU tar --transform rules.
with tempfile.TemporaryDirectory(prefix="hermes-ssh-bulk-") as staging:
for host_path, remote_path in files:
staged = os.path.join(staging, remote_path.lstrip("/"))
try:
rel_remote = os.path.relpath(remote_path, base)
except ValueError as exc:
raise RuntimeError(
f"remote path {remote_path!r} is not under sync base {base!r}"
) from exc
if rel_remote == "." or rel_remote.startswith("../"):
raise RuntimeError(
f"remote path {remote_path!r} escapes sync base {base!r}"
)
staged = os.path.join(staging, rel_remote)
os.makedirs(os.path.dirname(staged), exist_ok=True)
os.symlink(os.path.abspath(host_path), staged)
@ -190,7 +203,7 @@ class SSHEnvironment(BaseEnvironment):
# existing directories (e.g. /home/<user>) with the staging
# directory's mode. Without this, a umask 002 produces 0775
# dirs which breaks sshd StrictModes (refuses authorized_keys).
ssh_cmd.append("tar xf - --no-overwrite-dir -C /")
ssh_cmd.append(f"tar xf - --no-overwrite-dir -C {shlex.quote(base)}")
tar_proc = subprocess.Popen(
tar_cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE