{"record":{"id":"37aa46a97a76ed23","repo":"Fosowl/agenticSeek","slug":"path-path-is-outside-the-agent-workspace-bas","errorCode":null,"errorMessage":"Path '{path}' is outside the agent workspace ({base})","messagePattern":"Path '(.+?)' is outside the agent workspace \\((.+?)\\)","errorType":"validation","errorClass":"PermissionError","httpStatus":null,"severity":"error","filePath":"sources/workspace.py","lineNumber":90,"sourceCode":"    \"\"\"\n    Resolve a user or model-provided path inside the agent workspace.\n\n    Raises:\n        ValueError: empty path\n        PermissionError: resolved path escapes the workspace\n    \"\"\"\n    if path is None or not str(path).strip():\n        raise ValueError(\"Empty path\")\n\n    base = work_dir or get_work_dir()\n    candidate = str(path).strip()\n    if os.path.isabs(candidate):\n        resolved = os.path.realpath(candidate)\n    else:\n        resolved = os.path.realpath(os.path.join(base, candidate))\n\n    if not is_within_directory(resolved, base):\n        raise PermissionError(\n            f\"Path '{path}' is outside the agent workspace ({base})\"\n        )\n    return resolved\n","sourceCodeStart":72,"sourceCodeEnd":94,"githubUrl":"https://github.com/Fosowl/agenticSeek/blob/ae57a2357745a9706cb12d0fd76d954c84d166fa/sources/workspace.py#L72-L94","documentation":"After resolving the candidate path with os.path.realpath, resolve_workspace_path() checks is_within_directory(resolved, base) and raises PermissionError if the resolved location escapes the workspace directory. This is a sandbox/containment guard: it blocks absolute paths pointing elsewhere and relative paths containing '..' traversal that would resolve outside the agent workspace.","triggerScenarios":"Calling resolve_workspace_path('/etc/passwd') with an absolute path outside the base; calling it with '../secrets.txt' or 'a/../../etc/hosts' where the realpath lands outside the workspace; a symlink inside the workspace pointing to an external target (realpath follows symlinks); changing work_dir so a previously valid path now resolves outside it.","commonSituations":"Agents accepting user-supplied file paths (path traversal attempts); symlinks in the workspace created by tools or test fixtures pointing to /tmp or home; environment migration where the workspace base moved but stored paths are absolute; misconfigured work_dir that is narrower than expected so legitimate relative paths escape it.","solutions":["Pass a path relative to the workspace (no leading '/', no '..' escaping it) or a path whose realpath is inside the workspace directory.","Pass the intended base explicitly via the work_dir parameter so the containment check is evaluated against the correct directory.","Remove or re-point symlinks inside the workspace that target external locations, since realpath resolves them and trips the check.","If external access is genuinely needed, copy/sync the resource into the workspace rather than bypassing the check; never weaken is_within_directory."],"exampleFix":"// before\nresolved = resolve_workspace_path('/home/dev/data/report.csv')\n// after\nresolved = resolve_workspace_path('data/report.csv')  # relative to workspace","handlingStrategy":"validation","validationCode":"import os\n\ndef path_is_inside_workspace(candidate, base):\n    base_real = os.path.realpath(base)\n    cand = str(candidate).strip()\n    if os.path.isabs(cand):\n        resolved = os.path.realpath(cand)\n    else:\n        resolved = os.path.realpath(os.path.join(base_real, cand))\n    return os.path.commonpath([resolved, base_real]) == base_real\n\nif not path_is_inside_workspace(user_path, work_dir):\n    raise PermissionError(f\"refusing path outside workspace: {user_path}\")","typeGuard":"def is_safe_relative_path(p) -> bool:\n    s = str(p)\n    return bool(s.strip()) and not s.startswith('/') and '..' not in os.path.normpath(s).split(os.sep)","tryCatchPattern":"try:\n    resolved = resolve_workspace_path(user_path, work_dir)\nexcept PermissionError as e:\n    logger.warning(\"workspace escape blocked: %s\", e)\n    raise HTTPException(status_code=400, detail=\"path must stay within the workspace\") from e","preventionTips":["Store and pass workspace-relative paths, never absolute paths.","Reject or normalize '..' segments in user-supplied paths before resolution.","Audit the workspace for symlinks that point outside it; recreate them as copies if needed.","When the base moves between environments, re-derive paths from the new base instead of persisting absolute ones.","Keep the containment check intact in code review; treat any bypass as a security regression."],"tags":["python","permissionerror","path-traversal","sandbox","security","workspace"],"backgroundTag":"path-outside-workspace","analyzedSha":"ae57a2357745a9706cb12d0fd76d954c84d166fa","analyzedAt":"2026-08-30T02:49:05.834Z","schemaVersion":2},"datasetVersion":"2026-08-30T03:17:51.788Z"}