abhigyanpatwari/GitNexus · error · SandboxError
extra read-only mount target must be absolute: {mount.target
Error message
extra read-only mount target must be absolute: {mount.target} What it means
Thrown by `command_prefix_for` when an `extra_read_only_mounts` target is not an absolute path or contains a `..` component. Bubblewrap `--ro-bind` targets inside the sandbox must be absolute and must not allow path traversal outside the workspace root.
Source
Thrown at eval/workflow_bench/proposer_sandbox.py:158
)
)
for mount in extra_read_only_mounts:
source = mount.source.expanduser().absolute()
try:
metadata = source.lstat()
resolved = source.resolve(strict=True)
except OSError as exc:
raise SandboxError(f"extra read-only mount is unavailable: {source}") from exc
if (
resolved != source
or stat.S_ISLNK(metadata.st_mode)
or not (stat.S_ISDIR(metadata.st_mode) or stat.S_ISREG(metadata.st_mode))
):
raise SandboxError(f"extra read-only mount must be real and non-symlink: {source}")
target = PurePosixPath(mount.target)
if not target.is_absolute() or ".." in target.parts:
raise SandboxError(f"extra read-only mount target must be absolute: {mount.target}")
additional.append(ReadOnlyMount(source=source, target=target.as_posix()))
return _sandbox_command_prefix(
bwrap=self.bwrap_bin,
clone=clone,
home=self.home,
temp=self.temp,
claude_bin=self.claude_host_bin,
mounts=(*self.read_only_mounts, *additional),
read_only_workspace=read_only_workspace,
unshare_network=unshare_network,
)
_TOKEN_PATTERNS = (
re.compile(r"sk-ant-[A-Za-z0-9_-]{8,}"),
re.compile(r"gh(?:p|o|u|s|r)_[A-Za-z0-9_]{8,}"),
re.compile(r"(?i)(authorization\s*[:=]\s*(?:bearer\s+)?)[^\s,;]+"),View on GitHub (pinned to d540b00184)
Solutions
- Make the target absolute and workspace-rooted: `target = f'{SANDBOX_WORKSPACE}/{name}'` with no `..` parts.
- Validate before constructing the mount: `t = PurePosixPath(target); assert t.is_absolute() and '..' not in t.parts`.
- Normalize user-supplied targets: `target = str(Path('/' + target).resolve())` to coerce absolute + strip `..`.
- If you intended a relative target, you must convert it — bubblewrap does not accept relative mount targets.
Example fix
# before: relative / traversal target
mount = ReadOnlyMount(source=oracle, target='oracle.json') # -> SandboxError
# or
mount = ReadOnlyMount(source=oracle, target='/workspace/../etc/oracle') # -> SandboxError
# after: absolute, workspace-rooted, no '..'
from pathlib import PurePosixPath
target = PurePosixPath('/workspace/oracle.json')
assert target.is_absolute() and '..' not in target.parts
mount = ReadOnlyMount(source=oracle, target=target.as_posix()) Defensive patterns
Strategy: validation
Validate before calling
from pathlib import PurePosixPath
def mount_target_is_safe(target: str) -> bool:
t = PurePosixPath(target)
return t.is_absolute() and ".." not in t.parts
mounts = [m for m in mounts if mount_target_is_safe(m.target)]
prefix = session.command_prefix_for(extra_read_only_mounts=mounts) Type guard
from pathlib import PurePosixPath
def is_safe_mount_target(target: str) -> bool:
"""True iff target is absolute and contains no '..' (no traversal)."""
t = PurePosixPath(target)
return t.is_absolute() and ".." not in t.parts Try / catch
try:
prefix = session.command_prefix_for(extra_read_only_mounts=mounts)
except SandboxError as exc:
if "target must be absolute" in str(exc):
# coerce to absolute, workspace-rooted, no '..'
from pathlib import Path
mounts = [
ReadOnlyMount(
source=m.source,
target=str(Path("/" + m.target).resolve()),
)
for m in mounts
]
prefix = session.command_prefix_for(extra_read_only_mounts=mounts)
raise Prevention
- Always build targets as `f"{SANDBOX_WORKSPACE}/{name}"` with no `..`.
- Normalize user-supplied targets: `str(Path('/' + target).resolve())`.
- Reject relative targets at the API boundary of your harness.
When it happens
Trigger: Calling `command_prefix_for(extra_read_only_mounts=[ReadOnlyMount(source=s, target=t)])` where `t` is relative (e.g. `oracle.json`), or contains `..` (e.g. `/workspace/../etc/passwd`). The guard at proposer_sandbox.py:157 rejects both.
Common situations: Passing a target like `str(path)` where `path` was relative by mistake; constructing the target from user input without normalizing; a target that tries to escape the sandbox via `..`; forgetting the leading slash.
Related errors
- {label} contains an unsafe path component: {relative}
- unsafe results artifact path: {relative_value!r}
- {label} must be a repository-relative path: {relative!r}
- {label} escapes its allowed repository root: {relative}
- sandbox_copy must be a repository-relative path: {raw!r}
AI-assisted analysis of abhigyanpatwari/GitNexus@d540b00184 (2026-08-12).
Data as JSON: /api/errors/a63e0d0740bb4b24.
Report an issue: GitHub.