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

  1. Make the target absolute and workspace-rooted: `target = f'{SANDBOX_WORKSPACE}/{name}'` with no `..` parts.
  2. Validate before constructing the mount: `t = PurePosixPath(target); assert t.is_absolute() and '..' not in t.parts`.
  3. Normalize user-supplied targets: `target = str(Path('/' + target).resolve())` to coerce absolute + strip `..`.
  4. 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

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


AI-assisted analysis of abhigyanpatwari/GitNexus@d540b00184 (2026-08-12). Data as JSON: /api/errors/a63e0d0740bb4b24. Report an issue: GitHub.