fix(env): safely quote ~/ subpaths in wrapped cd commands

This commit is contained in:
Yukipukii1 2026-04-24 14:38:00 +03:00 committed by Teknium
parent 6051fba9dc
commit 2950ce7037
No known key found for this signature in database
2 changed files with 30 additions and 4 deletions

View file

@ -60,6 +60,22 @@ class TestWrapCommand:
assert "cd ~" in wrapped
assert "cd '~'" not in wrapped
def test_tilde_subpath_with_spaces_uses_home_and_quotes_suffix(self):
env = _TestableEnv()
env._snapshot_ready = True
wrapped = env._wrap_command("ls", "~/my repo")
assert "cd $HOME/'my repo'" in wrapped
assert "cd ~/my repo" not in wrapped
def test_tilde_slash_maps_to_home(self):
env = _TestableEnv()
env._snapshot_ready = True
wrapped = env._wrap_command("ls", "~/")
assert "cd $HOME" in wrapped
assert "cd ~/" not in wrapped
def test_cd_failure_exit_126(self):
env = _TestableEnv()
env._snapshot_ready = True

View file

@ -368,6 +368,17 @@ class BaseEnvironment(ABC):
# Command wrapping
# ------------------------------------------------------------------
@staticmethod
def _quote_cwd_for_cd(cwd: str) -> str:
"""Quote a ``cd`` target while preserving ``~`` expansion."""
if cwd == "~":
return cwd
if cwd == "~/":
return "$HOME"
if cwd.startswith("~/"):
return f"$HOME/{shlex.quote(cwd[2:])}"
return shlex.quote(cwd)
def _wrap_command(self, command: str, cwd: str) -> str:
"""Build the full bash script that sources snapshot, cd's, runs command,
re-dumps env vars, and emits CWD markers."""
@ -379,10 +390,9 @@ class BaseEnvironment(ABC):
if self._snapshot_ready:
parts.append(f"source {self._snapshot_path} 2>/dev/null || true")
# cd to working directory — let bash expand ~ natively
quoted_cwd = (
shlex.quote(cwd) if cwd != "~" and not cwd.startswith("~/") else cwd
)
# Preserve bare ``~`` expansion, but rewrite ``~/...`` through
# ``$HOME`` so suffixes with spaces remain a single shell word.
quoted_cwd = self._quote_cwd_for_cd(cwd)
parts.append(f"builtin cd {quoted_cwd} || exit 126")
# Run the actual command