abhigyanpatwari/GitNexus · error · SandboxError
transcript artifact parent must be owner-only: {current}
Error message
transcript artifact parent must be owner-only: {current} What it means
For transcript artifacts only, _results_artifact_path requires the parent directory's permission bits to be owner-only: `stat.S_IMODE(mode) & 0o077` must be zero. Transcript content is sensitive (agent event streams), so a group/other-readable or writable parent is treated as a containment breach.
Source
Thrown at eval/workflow_bench/evolve.py:321
expected_parts = 2 if transcript else 1
if (
relative.is_absolute()
or len(relative.parts) != expected_parts
or any(part in {"", ".", ".."} for part in relative.parts)
or (transcript and relative.parts[0] != "transcripts")
):
raise SandboxError(f"unsafe results artifact path: {relative_value!r}")
current = root
for part in relative.parts[:-1]:
current /= part
try:
metadata = current.lstat()
except OSError as exc:
raise SandboxError(f"results artifact parent is unavailable: {current}: {exc}") from exc
if stat.S_ISLNK(metadata.st_mode) or not stat.S_ISDIR(metadata.st_mode):
raise SandboxError(f"results artifact parent must be a real directory: {current}")
if transcript and stat.S_IMODE(metadata.st_mode) & 0o077:
raise SandboxError(f"transcript artifact parent must be owner-only: {current}")
return root / Path(*relative.parts)
def _transcript_artifact_metadata(metadata: Any) -> tuple[str, str, int]:
"""Validate transcript metadata without touching any host path."""
if not isinstance(metadata, dict) or set(metadata) != {"path", "sha256", "bytes", "source"}:
raise SandboxError("transcript artifact metadata must contain only path, sha256, bytes, and source")
relative = metadata["path"]
expected_digest = metadata["sha256"]
expected_size = metadata["bytes"]
if metadata["source"] != runner_sessions.PARENT_EVENT_STREAM_SOURCE:
raise SandboxError("transcript artifact source is not the parent event stream")
if not isinstance(relative, str) or not re.fullmatch(r"[0-9a-f]{64}", str(expected_digest)):
raise SandboxError("transcript artifact metadata is malformed")
if not isinstance(expected_size, int) or isinstance(expected_size, bool):
raise SandboxError("transcript artifact byte count must be an integer")
if expected_size < 0 or expected_size > runner.MAX_TRANSCRIPT_BYTES:View on GitHub (pinned to d540b00184)
Solutions
- Tighten the parent: `chmod 700 <results_dir>/transcripts` (or 0700/0500).
- Re-extract any results tarball with `umask 077` first.
- Audit the whole results tree: `find <results_dir> -type d -perm /077` and fix each hit.
Example fix
# before
chmod -R g+rwX results/transcripts # group/other bits now set
# after
chmod 700 results/transcripts
find results -type d -perm /077 -exec chmod o-rwx,g-rwx {} + Defensive patterns
Strategy: validation
Validate before calling
import stat
from pathlib import Path, PurePosixPath
def transcript_parents_owner_only(root: Path, relative_value: str) -> bool:
current = root
for part in PurePosixPath(relative_value).parts[:-1]:
current /= part
m = current.lstat().st_mode
if stat.S_IMODE(m) & 0o077:
return False
return True
# enforce before proposing
import os
os.chmod(root / "transcripts", 0o700) Prevention
- Create transcript dirs with mode 0o700 from the start.
- Extract results tarballs with `umask 077`.
- Audit with `find <results_dir> -type d -perm /077` in CI.
When it happens
Trigger: The transcripts directory (or any ancestor in the artifact path) has group or other bits set: chmod g+r, o+r, g+w, etc.; results copied with a permissive umask; a shared volume with宽松 mode.
Common situations: Results tree on a shared/group-writable volume; files copied with `cp -a` from a permissive source; CI that runs chmod 775 on artifacts; tarballs extracted with group inheritance.
Related errors
- evidence source must be a regular non-symlink file: {path}
- results directory must not traverse symlinks: {root}
- results artifact parent must be a real directory: {current}
- transcript artifact source is not the parent event stream
- transcript artifact must be owner-only: {path}
AI-assisted analysis of abhigyanpatwari/GitNexus@d540b00184 (2026-08-12).
Data as JSON: /api/errors/7777613213a30f3e.
Report an issue: GitHub.