fix(exec): preserve bwrap workspace masking

This commit is contained in:
Xubin Ren
2026-07-27 00:31:00 +08:00
parent 22e61003f9
commit cf6ca13b6d
5 changed files with 80 additions and 9 deletions
+18 -4
View File
@@ -13,7 +13,11 @@ from typing import Iterable
from nanobot.config.paths import get_media_dir
def _normalize_bind_paths(paths: Iterable[str] | None) -> list[str]:
def _normalize_bind_paths(
paths: Iterable[str] | None,
*,
workspace: Path | None = None,
) -> list[str]:
out: list[str] = []
seen: set[str] = set()
for raw in paths or []:
@@ -23,7 +27,17 @@ def _normalize_bind_paths(paths: Iterable[str] | None) -> list[str]:
path = Path(os.path.expandvars(value)).expanduser()
if not path.is_absolute():
continue
resolved = str(path.resolve(strict=False))
resolved_path = path.resolve(strict=False)
if workspace is not None:
try:
workspace.relative_to(resolved_path)
except ValueError:
pass
else:
# A later bind of the workspace or one of its parents could
# cover the tmpfs that hides the config directory.
continue
resolved = str(resolved_path)
if resolved in seen:
continue
seen.add(resolved)
@@ -79,9 +93,9 @@ def _bwrap(
"--bind", str(ws), str(ws),
"--ro-bind-try", str(media), str(media), # read-only access to media
]
for p in _normalize_bind_paths(sandbox_ro_binds):
for p in _normalize_bind_paths(sandbox_ro_binds, workspace=ws):
args += ["--ro-bind-try", p, p]
for p in _normalize_bind_paths(sandbox_rw_binds):
for p in _normalize_bind_paths(sandbox_rw_binds, workspace=ws):
args += ["--bind-try", p, p]
args += ["--chdir", sandbox_cwd, "--", "sh", "-c", command]
return shlex.join(args)
+15 -3
View File
@@ -809,7 +809,9 @@ class ExecTool(Tool):
if workspace_root
else None
)
sandbox_bind_roots = self._active_sandbox_bind_roots()
sandbox_bind_roots = self._active_sandbox_bind_roots(
resolved_workspace or cwd_path
)
for raw in self._extract_absolute_paths(cmd):
try:
@@ -960,7 +962,17 @@ class ExecTool(Tool):
roots.append(resolved)
return roots
def _active_sandbox_bind_roots(self) -> list[Path]:
def _active_sandbox_bind_roots(
self,
workspace_root: Path | None = None,
) -> list[Path]:
if self.sandbox != "bwrap" or _IS_WINDOWS:
return []
return [*self.sandbox_ro_binds, *self.sandbox_rw_binds]
roots = [*self.sandbox_ro_binds, *self.sandbox_rw_binds]
if workspace_root is None:
return roots
return [
root
for root in roots
if not is_path_within(workspace_root, root)
]