Fosowl/agenticSeek · error · PermissionError

Path '{path}' is outside the agent workspace ({base})

Error message

Path '{path}' is outside the agent workspace ({base})

What it means

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.

Source

Thrown at sources/workspace.py:90

    """
    Resolve a user or model-provided path inside the agent workspace.

    Raises:
        ValueError: empty path
        PermissionError: resolved path escapes the workspace
    """
    if path is None or not str(path).strip():
        raise ValueError("Empty path")

    base = work_dir or get_work_dir()
    candidate = str(path).strip()
    if os.path.isabs(candidate):
        resolved = os.path.realpath(candidate)
    else:
        resolved = os.path.realpath(os.path.join(base, candidate))

    if not is_within_directory(resolved, base):
        raise PermissionError(
            f"Path '{path}' is outside the agent workspace ({base})"
        )
    return resolved

View on GitHub (pinned to ae57a23577)

Solutions

  1. Pass a path relative to the workspace (no leading '/', no '..' escaping it) or a path whose realpath is inside the workspace directory.
  2. Pass the intended base explicitly via the work_dir parameter so the containment check is evaluated against the correct directory.
  3. Remove or re-point symlinks inside the workspace that target external locations, since realpath resolves them and trips the check.
  4. If external access is genuinely needed, copy/sync the resource into the workspace rather than bypassing the check; never weaken is_within_directory.

Example fix

// before
resolved = resolve_workspace_path('/home/dev/data/report.csv')
// after
resolved = resolve_workspace_path('data/report.csv')  # relative to workspace
Defensive patterns

Strategy: validation

Validate before calling

import os

def path_is_inside_workspace(candidate, base):
    base_real = os.path.realpath(base)
    cand = str(candidate).strip()
    if os.path.isabs(cand):
        resolved = os.path.realpath(cand)
    else:
        resolved = os.path.realpath(os.path.join(base_real, cand))
    return os.path.commonpath([resolved, base_real]) == base_real

if not path_is_inside_workspace(user_path, work_dir):
    raise PermissionError(f"refusing path outside workspace: {user_path}")

Type guard

def is_safe_relative_path(p) -> bool:
    s = str(p)
    return bool(s.strip()) and not s.startswith('/') and '..' not in os.path.normpath(s).split(os.sep)

Try / catch

try:
    resolved = resolve_workspace_path(user_path, work_dir)
except PermissionError as e:
    logger.warning("workspace escape blocked: %s", e)
    raise HTTPException(status_code=400, detail="path must stay within the workspace") from e

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of Fosowl/agenticSeek@ae57a23577 (2026-08-30). Data as JSON: /api/errors/37aa46a97a76ed23. Report an issue: GitHub.