Skip to content

Commit 072c721

Browse files
isaacbmillerampagentIsaac Miller
authored
Reject colliding PythonInterpreter file mounts (#10205)
* Reject unsafe PythonInterpreter mounts Amp-Thread-ID: https://ampcode.com/threads/T-019fcce1-bc8b-753e-886f-9b77c0ccb376 Co-authored-by: Isaac Miller <isaac@cmpnd.ai> * Revert "Reject unsafe PythonInterpreter mounts" This reverts commit 8729b56. Co-authored-by: Isaac Miller <isaac@cmpnd.ai> * Reject colliding PythonInterpreter mounts Amp-Thread-ID: https://ampcode.com/threads/T-019fcce1-bc8b-753e-886f-9b77c0ccb376 Co-authored-by: Isaac Miller <isaac@cmpnd.ai> * Handle aliased mount collisions Amp-Thread-ID: https://ampcode.com/threads/T-019fcce1-bc8b-753e-886f-9b77c0ccb376 Co-authored-by: Isaac Miller <isaac@cmpnd.ai> --------- Co-authored-by: Amp <amp@ampcode.com> Co-authored-by: Isaac Miller <isaac@cmpnd.ai>
1 parent 07a0f7a commit 072c721

2 files changed

Lines changed: 36 additions & 0 deletions

File tree

‎dspy/primitives/python_interpreter.py‎

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -267,6 +267,14 @@ def __init__(
267267

268268
self.enable_read_paths = enable_read_paths or []
269269
self.enable_write_paths = enable_write_paths or []
270+
mounts = {}
271+
for path in [*self.enable_read_paths, *self.enable_write_paths]:
272+
if path:
273+
virtual_path = os.path.basename(os.fspath(path))
274+
host_path = _canonicalize_path(path)
275+
if virtual_path in mounts and mounts[virtual_path] != host_path:
276+
raise CodeInterpreterError("Mounted files must have unique basenames inside the sandbox.")
277+
mounts[virtual_path] = host_path
270278
self.enable_env_vars = enable_env_vars or []
271279
self.enable_network_access = enable_network_access or []
272280
self.sync_files = sync_files

‎tests/primitives/test_python_interpreter.py‎

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -413,6 +413,34 @@ def test_custom_deno_command_is_unchanged():
413413
assert interpreter.deno_command is not command
414414

415415

416+
def test_rejects_mounts_with_the_same_guest_basename(tmp_path):
417+
first = tmp_path / "first" / "shared.txt"
418+
second = tmp_path / "second" / "shared.txt"
419+
first.parent.mkdir()
420+
second.parent.mkdir()
421+
422+
with pytest.raises(CodeInterpreterError, match="unique basenames"):
423+
PythonInterpreter(deno_command=["deno"], enable_read_paths=[first], enable_write_paths=[second])
424+
425+
426+
def test_allows_same_canonical_file_as_read_and_write_mount(tmp_path):
427+
path = tmp_path / "shared.txt"
428+
429+
PythonInterpreter(deno_command=["deno"], enable_read_paths=[path], enable_write_paths=[path])
430+
431+
432+
def test_rejects_alias_basename_colliding_with_another_file(tmp_path):
433+
first = tmp_path / "first.txt"
434+
second = tmp_path / "second" / "shared.txt"
435+
alias = tmp_path / "alias" / "shared.txt"
436+
second.parent.mkdir()
437+
alias.parent.mkdir()
438+
alias.symlink_to(first)
439+
440+
with pytest.raises(CodeInterpreterError, match="unique basenames"):
441+
PythonInterpreter(deno_command=["deno"], enable_read_paths=[first, alias, second])
442+
443+
416444
def test_custom_deno_command_preserves_environment(monkeypatch):
417445
monkeypatch.setenv("DENO_NO_PACKAGE_JSON", "0")
418446
captured = {}

0 commit comments

Comments
 (0)