Skip to content

git_operations: every diff fails — -c diff.external= makes git execute an empty program #5979

Description

@YellowSnnowmann

What

git_operations' diff operation fails for every repository on main:

Git command failed: error: cannot run : No such file or directory
fatal: external diff died, stopping at <file>

Root cause

hardened_git injects every entry of NEUTRALISED_CONFIG as a -c override (src/openhuman/tools/impl/filesystem/git_operations_config.rs), and one of them is:

"diff.external=",

The intent is to neutralise a repository-set external diff driver. But git -c diff.external= does not disable the driver — it sets it to the empty string, and git then tries to execute that empty string. Reproducible on a bare repo with no config of its own:

$ git init -q . && echo a > f.txt && git add f.txt && git commit -qm init && echo b >> f.txt

$ git -c diff.external= diff -- f.txt
error: cannot run : No such file or directory
fatal: external diff died, stopping at f.txt

$ git -c diff.external= diff --no-ext-diff -- f.txt
diff --git a/f.txt b/f.txt
...                      # correct output

Every other entry in that list happens to name a program that exists or a key git treats as inert (core.pager=cat, core.editor=false, sequence.editor=false); diff.external is the one where an empty value means "run the empty program" rather than "none".

Impact

GitOperationsTool builds its diff through hardened_git (git_operations.rs, git_args = vec!["diff", "--unified=3"]), so the agent's diff operation is broken for all users, not only in tests. log/show are affected wherever they produce a patch.

How it surfaced

The raw-coverage test tools_network_channels_raw_coverage_e2e::git_operations_cover_read_write_markdown_and_safety_rejections fails on it. It is not caught on every PR because the coverage lane derives which raw-coverage modules to run from the changed paths, so it only runs when something under src/openhuman/tools/impl/filesystem/ is in the diff. It failed on #5955 purely because that PR merged main.

Fix

diff.external cannot be neutralised by a -c value — there is no value meaning "none". Drop it from NEUTRALISED_CONFIG and pass --no-ext-diff on the subcommands that honour an external diff driver (diff, and log/show when they produce a patch). GIT_EXTERNAL_DIFF is already cleared by suppress_ambient_git_config, so the env half of the hole is closed.

Acceptance criteria

  • git_operations diff succeeds on a repository with no external diff driver configured
  • A repository-set diff.external naming a program is still not executed (the hardening's actual goal), with a regression test that sets one and asserts it does not run
  • tools_network_channels_raw_coverage_e2e::git_operations_cover_read_write_markdown_and_safety_rejections passes
  • Any other NEUTRALISED_CONFIG entry whose empty value is command-valued is audited the same way

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Labels

No labels
No labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions