abhigyanpatwari/GitNexus · critical · SandboxError

dependency symlink escapes the sandbox workspace: {entry.pat

Error message

dependency symlink escapes the sandbox workspace: {entry.path}

What it means

_validate_dependency_symlinks resolves each symlink-kind dependency entry under the sandbox mount (/workspace/<mount_target>) and rejects it if the resolved path is neither /workspace itself nor located beneath /workspace. Dependency symlinks are permitted, but only if they stay inside the sandbox boundary.

Source

Thrown at eval/workflow_bench/task_assets.py:681

    container: Path,
    entries: tuple[AssetManifestEntry, ...],
    *,
    mount_target: PurePosixPath,
) -> None:
    snapshot_boundary = (container / "payload").resolve(strict=True)
    manifest_boundary = PurePosixPath("payload")
    sandbox_boundary = PurePosixPath(SANDBOX_WORKSPACE)
    sandbox_mount = sandbox_boundary / mount_target
    for entry in entries:
        if entry.kind != "symlink":
            continue
        target = PurePosixPath(entry.link_target)
        relative_to_payload = entry.path.relative_to(manifest_boundary)
        sandbox_resolved = PurePosixPath(
            posixpath.normpath((sandbox_mount / relative_to_payload.parent / target).as_posix())
        )
        if sandbox_resolved != sandbox_boundary and sandbox_boundary not in sandbox_resolved.parents:
            raise SandboxError(f"dependency symlink escapes the sandbox workspace: {entry.path}")
        manifest_resolved = PurePosixPath(posixpath.normpath((entry.path.parent / target).as_posix()))
        if manifest_resolved != manifest_boundary and manifest_boundary not in manifest_resolved.parents:
            continue
        link = container / Path(*entry.path.parts)
        try:
            resolved = link.resolve(strict=True)
            resolved.relative_to(snapshot_boundary)
        except (OSError, RuntimeError, ValueError) as exc:
            raise SandboxError(f"dependency symlink is dangling or escapes its snapshot: {entry.path}") from exc


def _preflight_exact_root(clone: Path, relative: PurePosixPath) -> None:
    """Reject symlink/special hazards while permitting replaceable type conflicts."""

    flags = os.O_RDONLY | os.O_DIRECTORY | getattr(os, "O_CLOEXEC", 0) | getattr(os, "O_NOFOLLOW", 0)
    current = os.open(clone, flags)
    try:
        for index, part in enumerate(relative.parts):

View on GitHub (pinned to d540b00184)

Solutions

  1. Inspect entry.link_target for the offending dependency and confirm it is relative and stays beneath /workspace
  2. Rebuild the dependency snapshot without escaping symlinks
  3. Fix the mount_target so the resolved link stays inside /workspace
Defensive patterns

Strategy: validation

Validate before calling

import posixpath
from pathlib import PurePosixPath

SANDBOX_WORKSPACE = "/workspace"

def escaping_links(entries, mount_target: str) -> list[str]:
    boundary = PurePosixPath(SANDBOX_WORKSPACE)
    mount = boundary / PurePosixPath(mount_target)
    manifest_boundary = PurePosixPath("payload")
    bad = []
    for e in entries:
        if e.get("kind") != "symlink":
            continue
        rel = PurePosixPath(e["path"]).relative_to(manifest_boundary)
        tgt = PurePosixPath(e["link_target"])
        resolved = PurePosixPath(posixpath.normpath((mount / rel.parent / tgt).as_posix()))
        if resolved != boundary and boundary not in resolved.parents:
            bad.append(e["path"])
    return bad

Try / catch

from eval.workflow_bench.proposer_sandbox import SandboxError

try:
    snapshot = cache.prepare(task, repo=repo, resolved_sha=sha)
except SandboxError as exc:
    if "escapes the sandbox workspace" in str(exc):
        raise SystemExit(f"dependency symlink escapes /workspace; rebuild the dependency: {exc}") from exc
    raise

Prevention

When it happens

Trigger: A dependency snapshot captures a symlink whose link_target, when joined onto its parent under the mount, resolves to an absolute path or a ../../ chain that lands outside /workspace; a misconfigured mount_target shifts the resolved root.

Common situations: A dependency tarball ships an absolute symlink (e.g. to /etc/passwd); a symlink with many parent traversals; the mount_target was changed without re-validating link targets.

Related errors


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