fix(daytona): quote single-upload mkdir parent path (#54440)

* fix(daytona): quote single-upload mkdir parent path

The single-file _daytona_upload() path shelled out 'mkdir -p {parent}'
with the remote parent interpolated unquoted, so shell metacharacters in
the path could break the command or inject arbitrary commands into the
sandbox. The bulk-upload, bulk-download, and delete paths were already
hardened with shlex-quoting helpers; this single-upload path was missed.

Route it through the existing quoted_mkdir_command() helper and add a
regression test covering a path with shell metacharacters.

Reported by @Gutslabs (#3960); the original branch predated the
file_sync refactor, so the fix is re-applied to the current code path.

* docs(infographic): daytona quote-sync fix
This commit is contained in:
Teknium 2026-06-28 14:33:03 -07:00 committed by GitHub
parent c648ecdca5
commit e5d22ab80d
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 28 additions and 1 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 MiB

View file

@ -413,3 +413,30 @@ class TestEnsureSandboxReady:
env._sandbox.state = "started"
env._ensure_sandbox_ready()
env._sandbox.start.assert_not_called()
# ---------------------------------------------------------------------------
# Sync safety: shell-metacharacter quoting
# ---------------------------------------------------------------------------
class TestSyncSafety:
def test_single_upload_quotes_parent_path(self, make_env, tmp_path):
"""A remote path with shell metacharacters must be quoted, not injected."""
env = make_env()
env._sandbox.process.exec.reset_mock()
host_file = tmp_path / "token.txt"
host_file.write_text("secret", encoding="utf-8")
remote_path = "/root/.hermes/skills/evil; touch /tmp/daytona-owned/file.txt"
env._daytona_upload(str(host_file), remote_path)
mkdir_cmd = env._sandbox.process.exec.call_args_list[0][0][0]
# The whole parent dir is a single quoted argument — the ';' cannot
# break out into a second command.
assert mkdir_cmd == (
"mkdir -p '/root/.hermes/skills/evil; touch /tmp/daytona-owned'"
)
assert "; touch" not in mkdir_cmd.replace(
"'/root/.hermes/skills/evil; touch /tmp/daytona-owned'", ""
)

View file

@ -154,7 +154,7 @@ class DaytonaEnvironment(BaseEnvironment):
def _daytona_upload(self, host_path: str, remote_path: str) -> None:
"""Upload a single file via Daytona SDK."""
parent = str(Path(remote_path).parent)
self._sandbox.process.exec(f"mkdir -p {parent}")
self._sandbox.process.exec(quoted_mkdir_command([parent]))
self._sandbox.fs.upload_file(host_path, remote_path)
def _daytona_bulk_upload(self, files: list[tuple[str, str]]) -> None: