shareAI-lab/learn-claude-code · error · ValueError
Path escapes workspace: {path}
Error message
Path escapes workspace: {path} What it means
safe_path() resolves a user/model-supplied relative path against a base (the given cwd or WORKDIR) and requires the result to stay inside that base. Any absolute path outside the workspace, or a relative path using ../ that climbs out, is rejected before any file operation. It is the central confinement guard for read/write/edit/bash tools.
Source
Thrown at s15_integrated_harness/code.py:804
"\nUse load_skill(name) when a skill is relevant.")
if context.get("memory_catalog"):
sections.append(f"Memory catalog:\n{context['memory_catalog']}")
if context.get("memories"):
sections.append(f"Relevant memory records:\n{context['memories']}")
mcp_names = list(mcp_clients.keys())
if mcp_names:
sections.append(f"Connected MCP servers: {', '.join(mcp_names)}")
return "\n\n".join(sections)
# -- Basic Tools --
def safe_path(path: str, cwd: Path | None = None) -> Path:
base = (cwd or WORKDIR).resolve()
resolved = (base / path).resolve()
if not resolved.is_relative_to(base):
raise ValueError(f"Path escapes workspace: {path}")
return resolved
_shell_processes: set[subprocess.Popen] = set()
_shell_process_lock = threading.RLock()
def _stop_process_group(process: subprocess.Popen):
"""Stop processes that remain in the command's original process group."""
for sig in (signal.SIGTERM, signal.SIGKILL):
try:
os.killpg(process.pid, sig)
except ProcessLookupError:
return
except OSError:
return
time.sleep(0.05)
View on GitHub (pinned to 985456f4ad)
Solutions
- Use paths relative to the workspace root (or the tool's cwd) and stay inside it.
- If a file legitimately lives outside, copy it into the workspace first with shell access permitted by policy.
- Expand and pre-check paths caller-side: resolve against base and confirm is_relative_to before calling file tools.
Example fix
// before
read_file("../../etc/hosts")
// after
read_file("notes/etc-hosts-copy.txt") // work inside WORKDIR Defensive patterns
Strategy: type-guard
Validate before calling
from pathlib import Path
def inside_workspace(path: str, base: Path) -> bool:
try:
return (base / path).resolve().is_relative_to(base.resolve())
except (TypeError, ValueError):
return False Type guard
def is_safe_relative(path: str) -> bool:
return isinstance(path, str) and not path.startswith(("/", "~")) and ".." not in Path(path).parts Try / catch
try:
resolved = safe_path(path, cwd)
except ValueError as e:
if "escapes workspace" in str(e):
return f"Error: {e}. Use a path inside the workspace."
raise Prevention
- Always use workspace-relative paths in tool calls.
- Reject absolute paths and '..' segments before calling file tools.
- Remember '~' is not expanded — pass real relative paths.
When it happens
Trigger: Passing '/etc/passwd' or '~/secrets' (unexpanded) to a file tool; 'build/../../outside.txt'; a cwd argument that is itself outside WORKDIR combined with a relative path escaping it. Note ~ is NOT expanded, so '~/x' resolves under base as a literal '~' directory — paths outside base raise here.
Common situations: Model writing absolute paths from error messages; agents following a symlinked include to a system file; scripts assuming home-directory access inside a sandboxed harness.
Related errors
- Path escapes workspace: {p}
- Path escapes workspace: {p}
- Path escapes workspace: {p}
- Path escapes workspace: {p}
- Path escapes workspace: {p}
AI-assisted analysis of shareAI-lab/learn-claude-code@985456f4ad (2026-08-14).
Data as JSON: /api/errors/a4ddedceafcf4af1.
Report an issue: GitHub.