{"record":{"id":"2fbfe313a3171288","repo":"abhigyanpatwari/GitNexus","slug":"dependency-target-must-stay-inside-the-clone-tar","errorCode":null,"errorMessage":"dependency target must stay inside the clone: {target_path}","messagePattern":"dependency target must stay inside the clone: (.+?)","errorType":"exception","errorClass":"SandboxError","httpStatus":null,"severity":"error","filePath":"eval/workflow_bench/task_assets.py","lineNumber":582,"sourceCode":"    raw_declarations = task.get(\"sandbox_dependencies\", [])\n    if not isinstance(raw_declarations, list):\n        raise SandboxError(\"sandbox_dependencies must be a list\")\n    declarations: list[_DependencyDeclaration] = []\n    for item in raw_declarations:\n        if (\n            not isinstance(item, Mapping)\n            or set(item) != {\"source\", \"target\"}\n            or not all(isinstance(item[field], str) and item[field] for field in (\"source\", \"target\"))\n        ):\n            raise SandboxError(\"sandbox_dependencies entries require only nonblank source and target\")\n        source = str(item[\"source\"])\n        target = str(item[\"target\"])\n        source_path = PurePosixPath(source)\n        target_path = PurePosixPath(target)\n        if source_path.is_absolute() or \"..\" in source_path.parts or not source_path.parts:\n            raise SandboxError(f\"dependency source must stay inside the repository: {source_path}\")\n        if target_path.is_absolute() or \"..\" in target_path.parts or not target_path.parts:\n            raise SandboxError(f\"dependency target must stay inside the clone: {target_path}\")\n        _validate_manifest_path(source_path)\n        _validate_manifest_path(target_path)\n        declarations.append(\n            _DependencyDeclaration(\n                source=source,\n                target=target,\n                source_path=source_path,\n                target_path=target_path,\n            )\n        )\n    for index, declaration in enumerate(declarations):\n        for other in declarations[index + 1 :]:\n            if (\n                declaration.target_path == other.target_path\n                or declaration.target_path in other.target_path.parents\n                or other.target_path in declaration.target_path.parents\n            ):\n                raise SandboxError(f\"sandbox dependency targets overlap: {declaration.target} and {other.target}\")","sourceCodeStart":564,"sourceCodeEnd":600,"githubUrl":"https://github.com/abhigyanpatwari/GitNexus/blob/d540b00184d71a896261ee02670da9a92d59d8f7/eval/workflow_bench/task_assets.py#L564-L600","documentation":"Raised by _sandbox_dependency_declarations when a dependency's `target` path is absolute, contains '..', or is empty. The target is a clone-relative mount point (where the dependency appears inside the arm clone under SANDBOX_WORKSPACE), so it must stay inside the clone. An escaping target would mount bytes outside the sandbox workspace, breaking containment. Note the asymmetry: source is repo-relative, target is clone-relative — both must be bounded relative paths.","triggerScenarios":"A dependency target like `/abs/mount`, `../escape`, `node_modules/../../../`, or `''`. Also a target that resolves to the clone root itself (empty parts). The check mirrors the source check: `target_path.is_absolute() or '..' in target_path.parts or not target_path.parts`.","commonSituations":"Author uses an absolute mount path. Confusing source and target semantics and using an absolute path for target. A templating bug that injects '..'. Mounting to a parent of the workspace.","solutions":["Rewrite each dependency target as a clean clone-relative path with no '..': `node_modules`, `vendor`, not `/mnt/dep` or `../outside`.","Remember the target is relative to the arm clone's SANDBOX_WORKSPACE, not the host filesystem.","Avoid targets that resolve to or above the workspace root.","Validate with the provided path guard before prepare() (see validationCode)."],"exampleFix":"// before\n{\"sandbox_dependencies\": [\n  {\"source\": \"node_modules\", \"target\": \"/arm/node_modules\"}\n]}\n\n// after\n{\"sandbox_dependencies\": [\n  {\"source\": \"node_modules\", \"target\": \"node_modules\"}\n]}","handlingStrategy":"type-guard","validationCode":"from pathlib import PurePosixPath\n\ndef validate_dependency_targets_relative(task: dict) -> None:\n    for d in task.get(\"sandbox_dependencies\", []):\n        tp = PurePosixPath(d[\"target\"])\n        if tp.is_absolute() or \"..\" in tp.parts or not tp.parts:\n            raise ValueError(f\"dependency target must stay inside clone: {tp}\")\n\nvalidate_dependency_targets_relative(task)","typeGuard":"from pathlib import PurePosixPath\n\ndef dependency_target_is_bounded(raw: str) -> bool:\n    p = PurePosixPath(raw)\n    return not p.is_absolute() and bool(p.parts) and \"..\" not in p.parts","tryCatchPattern":"from eval.workflow_bench.propposer_sandbox import SandboxError\n\ntry:\n    snapshot = cache.prepare(task, repo=repo, resolved_sha=sha)\nexcept SandboxError as exc:\n    if \"target must stay inside the clone\" in str(exc):\n        # rewrite the target as a clone-relative path\n        raise\n    raise","preventionTips":["Author dependency targets relative to the arm clone's SANDBOX_WORKSPACE with no '..'.","Never use absolute mount paths.","Validate targets with the path guard before prepare."],"tags":["sandbox","config","validation","dependencies","path-traversal","security","task-declaration"],"backgroundTag":null,"analyzedSha":"d540b00184d71a896261ee02670da9a92d59d8f7","analyzedAt":"2026-08-12T19:50:25.132Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}