HKUDS/Vibe-Trading · error · ValueError

artifact_path escapes the current run_dir

Error message

artifact_path escapes the current run_dir

What it means

When a relative artifact_path is supplied with a run_dir, the tool resolves run_dir/path and requires it to stay inside run_dir; '../' sequences that escape raise this. It is a path-traversal guard ensuring evidence files belong to the current run.

Source

Thrown at agent/src/tools/goal_tool.py:93

    artifact_path = str(kwargs.get("artifact_path") or "").strip() or None
    artifact_hash = str(kwargs.get("artifact_hash") or "").strip() or None

    run_dir_raw = str(kwargs.get("run_dir") or "").strip()
    run_dir: Path | None = None
    if run_dir_raw:
        run_dir = safe_run_dir(run_dir_raw)
        if run_id is None:
            run_id = run_dir.name

    artifact_candidate: Path | None = None
    if artifact_path:
        raw_path = Path(artifact_path).expanduser()
        if run_dir is not None and not raw_path.is_absolute():
            resolved = (run_dir / raw_path).resolve()
            try:
                resolved.relative_to(run_dir)
            except ValueError as exc:
                raise ValueError("artifact_path escapes the current run_dir") from exc
            artifact_candidate = resolved
            artifact_path = str(resolved)
        elif raw_path.is_absolute():
            artifact_candidate = raw_path.resolve()

    if artifact_candidate is not None and artifact_candidate.is_file() and not artifact_hash:
        artifact_hash = _sha256_file(artifact_candidate)

    return run_id, artifact_path, artifact_hash


class _GoalToolBase(BaseTool):
    """Shared helpers for local goal tools."""

    repeatable = True

    def __init__(
        self,

View on GitHub (pinned to 80ffdda44c)

Solutions

  1. Use a path relative to run_dir without '../' segments
  2. Use an absolute path to the artifact (absolute paths take the elif branch and are allowed if the file exists)
  3. Store shared artifacts inside run_dir or pass explicit artifact_hash instead of a path

Example fix

# before
execute(artifact_path="../run-42/report.md")
# after
execute(artifact_path="run-42/report.md", ...)  # or absolute path
Defensive patterns

Strategy: validation

Validate before calling

from pathlib import Path
p = Path(artifact_path)
if not p.is_absolute():
    assert ".." not in p.parts, f"artifact_path must stay inside run_dir: {artifact_path}"

Type guard

def path_is_within(path_str: str, run_dir) -> bool:
    from pathlib import Path
    p = Path(path_str)
    if p.is_absolute():
        return True
    try:
        (run_dir / p).resolve().relative_to(run_dir)
        return True
    except ValueError:
        return False

Try / catch

try:
    execute(artifact_path=artifact_path, ...)
except ValueError as e:
    if "escapes the current run_dir" in str(e):
        artifact_path = str((run_dir / Path(artifact_path).name).resolve())
        execute(artifact_path=artifact_path, ...)
    raise

Prevention

When it happens

Trigger: artifact_path='../../etc/passwd', 'logs/../../../secrets.txt', or any relative path whose resolved location leaves run_dir. Also symlinked run_dir contents pointing outside after resolve().

Common situations: LLM-generated artifact paths with ../; joined paths from inconsistent working directories; attempts to reference artifacts from prior runs stored elsewhere.

Understand the failure class

Background: Path traversal blocked: "path escapes the workspace" and "outside site root" errors when a path will not stay inside its allowed directory — this error's family across 26 libraries.

Related errors


AI-assisted analysis of HKUDS/Vibe-Trading@80ffdda44c (2026-08-28). Data as JSON: /api/errors/fc4752830565ca18. Report an issue: GitHub.