{"record":{"id":"28fef2fcc0edfe48","repo":"NousResearch/hermes-agent","slug":"path-resolved-is-outside-the-session-cwd-roo","errorCode":null,"errorMessage":"Path '{resolved}' is outside the session cwd '{root}'.","messagePattern":"Path '(.+?)' is outside the session cwd '(.+?)'\\.","errorType":"exception","errorClass":"PermissionError","httpStatus":null,"severity":"error","filePath":"agent/copilot_acp_client.py","lineNumber":379,"sourceCode":"        cursor = max(cursor, end)\n    if cursor < len(text):\n        parts.append(text[cursor:])\n\n    cleaned = \"\\n\".join(p.strip() for p in parts if p and p.strip()).strip()\n    return extracted, cleaned\n\n\n\ndef _ensure_path_within_cwd(path_text: str, cwd: str) -> Path:\n    candidate = Path(path_text)\n    if not candidate.is_absolute():\n        raise PermissionError(\"ACP file-system paths must be absolute.\")\n    resolved = candidate.resolve()\n    root = Path(cwd).resolve()\n    try:\n        resolved.relative_to(root)\n    except ValueError as exc:\n        raise PermissionError(f\"Path '{resolved}' is outside the session cwd '{root}'.\") from exc\n    return resolved\n\n\nclass _ACPChatCompletions:\n    def __init__(self, client: \"CopilotACPClient\"):\n        self._client = client\n\n    def create(self, **kwargs: Any) -> Any:\n        return self._client._create_chat_completion(**kwargs)\n\n\nclass _ACPChatNamespace:\n    def __init__(self, client: \"CopilotACPClient\"):\n        self.completions = _ACPChatCompletions(client)\n\n\nclass CopilotACPClient:\n    \"\"\"Minimal OpenAI-client-compatible facade for Copilot ACP.\"\"\"","sourceCodeStart":361,"sourceCodeEnd":397,"githubUrl":"https://github.com/NousResearch/hermes-agent/blob/c896c09c42910c584c4c7d2325b58c14713ea42c/agent/copilot_acp_client.py#L361-L397","documentation":"An ACP file-system request resolved to a path outside the session's cwd. After requiring an absolute path, _ensure_path_within_cwd resolves symlinks and requires the result to be relative_to(Path(cwd).resolve()); a ValueError from relative_to becomes this PermissionError. It confines the Copilot ACP process to the session workspace.","triggerScenarios":"An fs/read_text_file or fs/write_text_file from the Copilot ACP process targeting an absolute path outside the session cwd, or a path inside the cwd that is a symlink resolving outside it (candidate.resolve() follows links).","commonSituations":"Copilot CLI trying to read config or caches from $HOME while the session cwd is a project directory; symlinked dependencies (monorepo layouts) escaping the workspace; probing behavior from a misbehaving ACP peer.","solutions":["Run the session from a directory that contains everything the agent needs, so cwd covers the accessed paths.","Check for symlinks in the failing path (ls -l) and replace/relocate ones that escape the workspace.","If a legitimate need exists to work on multiple roots, start Hermes in a parent directory containing them."],"exampleFix":"# before — session started in subdir, Copilot reaches for sibling\nhermes  # cwd=/repo/packages/app  → path /repo/packages/lib/x.ts denied\n# after — start at the repo root so cwd contains both\nhermes  # cwd=/repo","handlingStrategy":"validation","validationCode":"from pathlib import Path\n\ndef within_cwd(path_text: str, cwd: str) -> bool:\n    resolved = Path(path_text).resolve()\n    try:\n        resolved.relative_to(Path(cwd).resolve())\n        return True\n    except ValueError:\n        return False","typeGuard":null,"tryCatchPattern":"try:\n    handle_fs_request(params)\nexcept PermissionError as e:\n    if \"outside the session cwd\" in str(e):\n        # relocate the work under cwd or restart session in a wider root\n        ...","preventionTips":["Start Hermes in a parent directory that contains all working files","Avoid symlinks that escape the session cwd","Keep Copilot-scoped work inside one workspace root"],"tags":["acp","copilot","security","workspace"],"backgroundTag":null,"analyzedSha":"c896c09c42910c584c4c7d2325b58c14713ea42c","analyzedAt":"2026-08-14T17:18:01.089Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}