{"record":{"id":"4ad4323259eeeefa","repo":"abhigyanpatwari/GitNexus","slug":"unsafe-git-object-id-orig-sha-r","errorCode":null,"errorMessage":"unsafe git object id: {orig_sha!r}","messagePattern":"unsafe git object id: (.+?)","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"critical","filePath":"eval/workflow_bench/runner_artifacts.py","lineNumber":383,"sourceCode":"    if not result.ok:\n        raise ManagedProcessError(command, result)\n    return result.stdout_tail\n\n\ndef _prepare_untracked_for_diff(sandbox: SandboxSession) -> None:\n    _sandbox_git(sandbox, [\"add\", \"--intent-to-add\", \"-A\"])\n\n\ndef implementation_diff_digest(\n    sandbox: SandboxSession,\n    orig_sha: str,\n    *,\n    prepare_untracked: bool = True,\n) -> str:\n    \"\"\"Digest non-plan final work entirely inside the containment boundary.\"\"\"\n\n    if not re.fullmatch(r\"[0-9a-fA-F]{40,64}\", orig_sha):\n        raise ValueError(f\"unsafe git object id: {orig_sha!r}\")\n    if prepare_untracked:\n        _prepare_untracked_for_diff(sandbox)\n    command = (\n        \"/usr/bin/git -c core.fsmonitor=false diff --no-ext-diff --no-textconv --binary \"\n        f\"{orig_sha} -- . ':(exclude)docs/plans' ':(exclude).claude/skills' \"\n        \"| /usr/bin/sha256sum\"\n    )\n    result = sandbox.run(\n        [\"/bin/sh\", \"-c\", command],\n        timeout=60,\n        env=build_sandbox_environment(),\n    )\n    if not result.ok:\n        raise ManagedProcessError(command, result)\n    digest = result.stdout_tail.strip().split()[0] if result.stdout_tail.strip() else \"\"\n    if not re.fullmatch(r\"[0-9a-f]{64}\", digest):\n        raise RuntimeError(\"sandboxed git diff did not produce a SHA-256 digest\")\n    return digest","sourceCodeStart":365,"sourceCodeEnd":401,"githubUrl":"https://github.com/abhigyanpatwari/GitNexus/blob/d540b00184d71a896261ee02670da9a92d59d8f7/eval/workflow_bench/runner_artifacts.py#L365-L401","documentation":"Thrown by implementation_diff_digest before orig_sha is interpolated into a shell command string. Because the SHA is substituted into a `/bin/sh -c` pipeline (`git diff <sha> -- ... | sha256sum`), it must be a bare hex object id; anything else is a command-injection vector. The regex [0-9a-fA-F]{40,64} accepts both SHA-1 (40) and SHA-256 (64) git object ids and rejects everything else.","triggerScenarios":"re.fullmatch(r'[0-9a-fA-F]{40,64}', orig_sha) fails — orig_sha is None, a shortened SHA, a ref name, contains uppercase G/z, or includes shell metacharacters.","commonSituations":"Caller passed a short SHA (git's abbreviated 7-12 chars) instead of the full id; passed a branch/tag ref; passed HEAD or a relative ref; the SHA came from an untrusted source and contains a newline/semicolon.","solutions":["Resolve to a full object id before calling: `git rev-parse <ref>^{commit}` and pass the 40/64-char hex output.","Never pass abbreviated SHAs, branch names, or HEAD to implementation_diff_digest.","If you compute orig_sha from agent output, validate it with the same regex before passing it in.","Treat any non-hex value as a programming error in the caller, not a runtime user input."],"exampleFix":"// before — passing a short sha\nimplementation_diff_digest(sandbox, orig_sha='abc1234')\n\n// after — resolve to a full object id first\nfull = run_checked(['git','-C',str(worktree),'rev-parse','HEAD^{commit}']).strip()\nimplementation_diff_digest(sandbox, orig_sha=full)","handlingStrategy":"validation","validationCode":"import re\n\ndef is_safe_object_id(sha: str) -> bool:\n    return isinstance(sha, str) and bool(re.fullmatch(r'[0-9a-fA-F]{40,64}', sha))","typeGuard":"import re\n\ndef is_full_sha(s: str) -> bool:\n    return isinstance(s, str) and bool(re.fullmatch(r'[0-9a-fA-F]{40,64}', s))","tryCatchPattern":"try:\n    implementation_diff_digest(sandbox, orig_sha)\nexcept ValueError as e:\n    if 'unsafe git object id' in str(e):\n        # resolve the ref to a full object id and retry\n        raise\n    raise","preventionTips":["Always resolve refs/SHAs with `git rev-parse <ref>^{commit}` before passing to diff functions.","Never pass abbreviated SHAs, branch names, or HEAD as orig_sha.","Validate with is_full_sha at the boundary where untrusted input enters.","Treat a non-hex orig_sha as a caller bug, not user input."],"tags":["security","command-injection","git","validation","workflow-bench"],"backgroundTag":null,"analyzedSha":"d540b00184d71a896261ee02670da9a92d59d8f7","analyzedAt":"2026-08-12T19:50:25.132Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}