nexu-io/open-design · error · SystemExit
path traversal detected in prompt_file for job {job_id}
Error message
path traversal detected in prompt_file for job {job_id} What it means
Raised in the main loop after resolving prompt_file: the resolved path is not inside run_dir (is_relative_to(run_dir) is False). Same traversal guard as input_images, applied to the prompt file so a manifest cannot read arbitrary files outside the run.
Source
Thrown at skills/hatch-pet/scripts/generate_pet_images.py:261
jobs = select_jobs(
manifest,
states=parse_states(args.states),
skip_base=args.skip_base,
job_ids=args.job_id,
)
raw_dir = run_dir / "raw"
completed = []
for job in jobs:
job_id = str(job.get("id"))
prompt_raw = job.get("prompt_file")
output_raw = job.get("output_path")
if not isinstance(prompt_raw, str) or not isinstance(output_raw, str):
raise SystemExit(f"job {job_id} is missing prompt_file or output_path")
prompt_file = (run_dir / prompt_raw).resolve()
output_image = (run_dir / output_raw).resolve()
if not prompt_file.is_relative_to(run_dir):
raise SystemExit(f"path traversal detected in prompt_file for job {job_id}")
if not output_image.is_relative_to(run_dir):
raise SystemExit(f"path traversal detected in output_path for job {job_id}")
print(f"Generating {job_id} with secondary fallback")
image_paths = path_list(run_dir, job)
if image_paths:
response = run_image_edit(
model=args.model,
prompt_file=prompt_file,
image_paths=image_paths,
output_json=raw_dir / f"{job_id}.response.json",
size=args.size,
api_key=api_key,
)
else:
response = run_image_generation(
model=args.model,
prompt_file=prompt_file,
output_json=raw_dir / f"{job_id}.response.json",View on GitHub (pinned to 5be4028344)
Solutions
- Make prompt_file relative to run_dir (e.g. prompts/rows/idle.md) with no ../ escapes.
- Copy the desired prompt into run_dir/prompts and reference it relatively.
- Regenerate prompts with prepare_pet_run.py, which writes them under prompts/.
- Rerun the job.
Example fix
// before (manifest) "prompt_file": "/home/user/prompts/idle.md" // after cp /home/user/prompts/idle.md /tmp/pet-run/prompts/rows/idle.md # manifest: "prompt_file": "prompts/rows/idle.md"
Defensive patterns
Strategy: validation
Validate before calling
def safe_prompt_path(run_dir: Path, raw: str) -> Path:
resolved = (run_dir / raw).resolve()
if not resolved.is_relative_to(run_dir):
raise SystemExit(f"prompt_file escapes run_dir: {raw}")
return resolved Type guard
def prompt_is_inside(run_dir: Path, raw: str) -> bool:
return (run_dir / raw).resolve().is_relative_to(run_dir) Prevention
- Keep prompt_file relative to run_dir (e.g. prompts/rows/idle.md).
- Regenerate prompts via prepare_pet_run.py rather than editing the manifest.
- Reject manifests produced on another machine that bake in absolute paths.
When it happens
Trigger: A job's prompt_file is an absolute path or contains ../ that escapes run_dir (e.g. "/etc/passwd" or "../../secrets/prompt.md").
Common situations: Hand-editing prompt_file to an absolute path for convenience; moving a run dir without updating relative paths; manifest copied across machines with absolute paths baked in.
Related errors
- path traversal detected in input_images for job {job.get('id
- path traversal detected in output_path for job {job_id}
- invalid brand id: ${input.brandId}
- invalid design system id: ${designSystemId}
- --image path "${rel}" resolves outside the project directory
AI-assisted analysis of nexu-io/open-design@5be4028344 (2026-08-12).
Data as JSON: /api/errors/f4afbd9a82579f09.
Report an issue: GitHub.