shareAI-lab/learn-claude-code · error · ValueError
Path escapes workspace: {p}
Error message
Path escapes workspace: {p} What it means
The s02 session's copy of safe_path(): it joins a relative path onto WORKDIR, resolves it, and raises this ValueError when the result falls outside WORKDIR. It is the shared gate for run_read and the other file tools introduced in that session. Because .resolve() follows symlinks, both explicit ../ traversal and symlink-based escapes are caught.
Source
Thrown at s02_tool_use/code.py:74
return "Error: Dangerous command blocked"
try:
r = subprocess.run(command, shell=True, cwd=WORKDIR,
capture_output=True, text=True,
encoding="utf-8", errors="replace", timeout=120)
out = (r.stdout + r.stderr).strip()
return out[:50000] if out else "(no output)"
except subprocess.TimeoutExpired:
return "Error: Timeout (120s)"
except (FileNotFoundError, OSError) as e:
return f"Error: {e}"
# -- New in s02: four tools --
def safe_path(p: str) -> Path:
path = (WORKDIR / p).resolve()
if not path.is_relative_to(WORKDIR):
raise ValueError(f"Path escapes workspace: {p}")
return path
def run_read(path: str, limit: int | None = None) -> str:
try:
lines = safe_path(path).read_text().splitlines()
if limit and limit < len(lines):
lines = lines[:limit] + [f"... ({len(lines) - limit} more lines)"]
return "\n".join(lines)
except Exception as e:
return f"Error: {e}"
def run_write(path: str, content: str) -> str:
try:
file_path = safe_path(path)
file_path.parent.mkdir(parents=True, exist_ok=True)
file_path.write_text(content)View on GitHub (pinned to 985456f4ad)
Solutions
- Express every path relative to WORKDIR with no .. components
- Convert legitimate absolute paths via Path(p).resolve().relative_to(WORKDIR.resolve())
- Remove or relocate symlinks inside WORKDIR that point outside it
- Confirm WORKDIR matches the project root the agent believes it is in
Example fix
// before
run_read("../shared/config.yaml")
// after
run_read("shared/config.yaml") # assuming shared/ lives under WORKDIR Defensive patterns
Strategy: validation
Validate before calling
from pathlib import Path
def safe_rel(p: str) -> str:
cand = Path(p)
if not cand.is_absolute():
cand = WORKDIR / cand
cand = cand.resolve()
assert cand.is_relative_to(WORKDIR.resolve()), f"{p} escapes workspace"
return str(cand.relative_to(WORKDIR.resolve()))
run_read(safe_rel(user_path)) Prevention
- Pass only relative paths without '..' segments
- Do not feed tool-echoed absolute paths back into file tools
- Resolve WORKDIR once at startup and use the real path
When it happens
Trigger: run_read("../../etc/passwd"); run_read("/etc/hosts") since joining an absolute path discards WORKDIR; a path stepping through a symlink inside WORKDIR that points to /usr or another outside location.
Common situations: Agents passing absolute paths echoed by earlier tool output; workspaces with vendored symlinked dependencies resolving outside the tree; WORKDIR and actual file location disagreeing after a project move.
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/e3e8ac7e3267e493.
Report an issue: GitHub.