{"record":{"id":"76dc620d9991ab8a","repo":"abhigyanpatwari/GitNexus","slug":"label-must-be-a-regular-non-symlink-file-path","errorCode":null,"errorMessage":"{label} must be a regular non-symlink file: {path}","messagePattern":"(.+?) must be a regular non-symlink file: (.+?)","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"eval/workflow_bench/evolution.py","lineNumber":94,"sourceCode":"\n    _require_real_directory(root, label=label)\n    current = root\n    for part in relative.parts:\n        if part in {\"\", \".\", \"..\"}:\n            raise ValueError(f\"{label} contains an unsafe path component: {relative}\")\n        current /= part\n        _require_real_directory(current, label=label)\n\n\ndef _bounded_regular_bytes(path: Path, *, limit: int, label: str) -> bytes:\n    \"\"\"Read one bounded regular file without following its leaf link.\"\"\"\n\n    try:\n        before = path.lstat()\n    except OSError as exc:\n        raise ValueError(f\"{label} is unreadable: {path}: {exc}\") from exc\n    if stat.S_ISLNK(before.st_mode) or not stat.S_ISREG(before.st_mode):\n        raise ValueError(f\"{label} must be a regular non-symlink file: {path}\")\n    if before.st_size > limit:\n        raise ValueError(f\"{label} exceeds the bounded evidence limit\")\n\n    descriptor = os.open(path, os.O_RDONLY | getattr(os, \"O_NOFOLLOW\", 0))\n    try:\n        opened = os.fstat(descriptor)\n        if not stat.S_ISREG(opened.st_mode) or opened.st_dev != before.st_dev or opened.st_ino != before.st_ino:\n            raise ValueError(f\"{label} changed while opening: {path}\")\n        chunks: list[bytes] = []\n        remaining = limit + 1\n        while remaining > 0:\n            chunk = os.read(descriptor, min(64 * 1024, remaining))\n            if not chunk:\n                break\n            chunks.append(chunk)\n            remaining -= len(chunk)\n        content = b\"\".join(chunks)\n        if len(content) > limit:","sourceCodeStart":76,"sourceCodeEnd":112,"githubUrl":"https://github.com/abhigyanpatwari/GitNexus/blob/d540b00184d71a896261ee02670da9a92d59d8f7/eval/workflow_bench/evolution.py#L76-L112","documentation":"Thrown by _bounded_regular_bytes() in eval/workflow_bench/evolution.py when lstat() succeeds but the entry is a symlink (S_ISLNK) or not a regular file (not S_ISREG): the evidence reader refuses to follow symlinks and refuses special files (FIFO/socket/device) because they could be used to escape or to deliver unbounded bytes.","triggerScenarios":"A candidate overlay file that is a symlink, a FIFO, a socket, or a device node. The reader opens with O_NOFOLLOW and rejects anything not a plain regular file before reading.","commonSituations":"Tarball that preserved symlinks; a user symlinked a shared skill file into many overlays; a misbehaving candidate generator that wrote a FIFO; an absolute symlink pointing outside the sandbox.","solutions":["Replace symlinks with real files: `cp -rL` to dereference at staging time.","Re-extract the candidate tarball with symlink dereference or filter non-regular entries.","Audit the candidate generator to write regular files only.","Treat special files as a security signal if provenance is untrusted."],"exampleFix":"# before\nln -s /etc/passwd /tmp/ov/leaked.yaml\n_bounded_regular_bytes(Path('/tmp/ov/leaked.yaml'), limit=L, label='candidate overlay file')\n# ValueError: candidate overlay file must be a regular non-symlink file\n\n# after\ncp /etc/passwd /tmp/ov/leaked.yaml   # or, better, drop the entry entirely","handlingStrategy":"validation","validationCode":"import os, stat\ndef ensure_regular_file(p: Path) -> None:\n    st = p.lstat()\n    if stat.S_ISLNK(st.st_mode) or not stat.S_ISREG(st.st_mode):\n        raise SystemExit(f'evidence must be a regular file, not symlink/special: {p}')\n# call before _bounded_regular_bytes","typeGuard":"def is_not_regular_file_error(exc: ValueError) -> bool:\n    return 'must be a regular non-symlink file' in str(exc)","tryCatchPattern":"try:\n    _bounded_regular_bytes(p, limit=L, label='candidate overlay file')\nexcept ValueError as e:\n    if is_not_regular_file_error(e):\n        # dereference with cp -L or drop the entry, then retry\n        raise\n    raise","preventionTips":["Dereference symlinks at staging time (cp -rL).","Filter non-regular entries when extracting candidate tarballs.","Audit candidate generators to emit regular files only."],"tags":["workflow-bench","validation","symlink","path","sandbox","security","evolution"],"backgroundTag":null,"analyzedSha":"d540b00184d71a896261ee02670da9a92d59d8f7","analyzedAt":"2026-08-12T19:50:25.132Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}