{"record":{"id":"ea935c7375bbfdd8","repo":"abhigyanpatwari/GitNexus","slug":"gitnexus-mcp-executable-must-stay-outside-sandbox","errorCode":null,"errorMessage":"GitNexus MCP executable must stay outside {SANDBOX_WORKSPACE}","messagePattern":"GitNexus MCP executable must stay outside (.+?)","errorType":"exception","errorClass":"SandboxError","httpStatus":null,"severity":"critical","filePath":"eval/workflow_bench/runner_sessions.py","lineNumber":102,"sourceCode":"    \"mcp__gitnexus__pdg_query\",\n    \"mcp__gitnexus__route_map\",\n    \"mcp__gitnexus__tool_map\",\n    \"mcp__gitnexus__shape_check\",\n    \"mcp__gitnexus__api_impact\",\n    \"mcp__gitnexus__trace\",\n    \"mcp__gitnexus__detect_changes\",\n)\nGITNEXUS_MUTATING_TOOLS = (\"mcp__gitnexus__rename\",)\nBUILTIN_AGENT_TOOLS = (\"Read\", \"Grep\", \"Glob\", \"Edit\", \"Write\", \"Bash\", \"Skill\")\n\n\ndef sandbox_mcp_config() -> str:\n    \"\"\"Credential-free MCP configuration using only the pinned harness runtime.\"\"\"\n\n    entrypoint = PurePosixPath(SANDBOX_GITNEXUS_ENTRYPOINT)\n    workspace = PurePosixPath(SANDBOX_WORKSPACE)\n    if not entrypoint.is_absolute() or entrypoint == workspace or workspace in entrypoint.parents:\n        raise SandboxError(f\"GitNexus MCP executable must stay outside {SANDBOX_WORKSPACE}\")\n\n    config = {\n        \"mcpServers\": {\n            \"gitnexus\": {\n                \"type\": \"stdio\",\n                \"command\": \"/usr/bin/env\",\n                \"args\": [\n                    \"-i\",\n                    f\"HOME={SANDBOX_HOME}\",\n                    f\"TMPDIR={SANDBOX_TMP}\",\n                    f\"GITNEXUS_HOME={SANDBOX_GITNEXUS_REGISTRY}\",\n                    f\"GITNEXUS_MCP_ALLOWED_REPOS={SANDBOX_WORKSPACE}\",\n                    f\"GITNEXUS_MCP_DEFAULT_REPO={SANDBOX_WORKSPACE}\",\n                    \"PATH=/usr/local/bin:/usr/bin:/bin\",\n                    \"LANG=C.UTF-8\",\n                    \"GIT_TERMINAL_PROMPT=0\",\n                    SANDBOX_NODE,\n                    SANDBOX_GITNEXUS_ENTRYPOINT,","sourceCodeStart":84,"sourceCodeEnd":120,"githubUrl":"https://github.com/abhigyanpatwari/GitNexus/blob/d540b00184d71a896261ee02670da9a92d59d8f7/eval/workflow_bench/runner_sessions.py#L84-L120","documentation":"Thrown by sandbox_mcp_config before building the sandboxed MCP server config. The GitNexus MCP entrypoint (the node script the sandboxed agent will invoke) must be an absolute path and must live strictly outside the sandbox workspace; if it were inside /workspace, the confined agent could overwrite or replace the very executable that powers its own tools, breaking the containment boundary. This is a SandboxError (a RuntimeError subclass).","triggerScenarios":"SANDBOX_GITNEXUS_ENTRYPOINT is not absolute, equals SANDBOX_WORKSPACE ('/workspace'), or has /workspace as a parent. I.e. the pinned MCP binary was installed under /workspace.","commonSituations":"GitNexus was installed into /workspace (e.g. npm install inside the worktree) so its dist/cli/index.js is under the workspace root; the entrypoint constant was overridden to a relative path; a misconfigured sandbox image mounted the install under /workspace.","solutions":["Install GitNexus into a directory outside /workspace (the harness default is /opt/gitnexus-style path via SANDBOX_GITNEXUS), so dist/cli/index.js is not under the workspace.","Set SANDBOX_GITNEXUS_ENTRYPOINT to an absolute path that is not /workspace and not beneath it.","Mount the MCP runtime read-only from a host path outside the workspace rather than installing it inside.","Rebuild the sandbox image with GitNexus in /opt or /usr/local."],"exampleFix":"// before — GitNexus installed under the workspace\nSANDBOX_GITNEXUS_ENTRYPOINT = '/workspace/gitnexus/dist/cli/index.js'  # -> raises\n\n// after — install outside the workspace\nSANDBOX_GITNEXUS_ENTRYPOINT = '/opt/gitnexus/dist/cli/index.js'","handlingStrategy":"validation","validationCode":"from pathlib import PurePosixPath\n\ndef entrypoint_outside_workspace(entrypoint: str, workspace: str = '/workspace') -> bool:\n    ep = PurePosixPath(entrypoint)\n    ws = PurePosixPath(workspace)\n    return ep.is_absolute() and ep != ws and ws not in ep.parents","typeGuard":"from pathlib import PurePosixPath\n\ndef entrypoint_outside_workspace(entrypoint: str, workspace: str = '/workspace') -> bool:\n    ep = PurePosixPath(entrypoint)\n    ws = PurePosixPath(workspace)\n    return ep.is_absolute() and ep != ws and ws not in ep.parents","tryCatchPattern":"from eval.workflow_bench.proposer_sandbox import SandboxError\ntry:\n    cfg = sandbox_mcp_config()\nexcept SandboxError as e:\n    if 'must stay outside' in str(e):\n        # install/mount GitNexus outside /workspace, then retry\n        raise\n    raise","preventionTips":["Install GitNexus into /opt or /usr/local, never under /workspace.","Keep SANDBOX_GITNEXUS_ENTRYPOINT an absolute path outside the workspace tree.","Mount the MCP runtime read-only from a host path outside the workspace.","Add a preflight assert entrypoint_outside_workspace(...) before sandbox_mcp_config()."],"tags":["security","sandbox-isolation","mcp","configuration","workflow-bench"],"backgroundTag":null,"analyzedSha":"d540b00184d71a896261ee02670da9a92d59d8f7","analyzedAt":"2026-08-12T19:50:25.132Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}