Skip to content

fix(git): route git_add(".") through the validated git CLI path - #4799

Open
Yash121l wants to merge 1 commit into
modelcontextprotocol:mainfrom
Yash121l:fix/git-add-skips-git-dir
Open

Yash121l wants to merge 1 commit into
modelcontextprotocol:mainfrom
Yash121l:fix/git-add-skips-git-dir

Conversation

@Yash121l

Copy link
Copy Markdown

Description

Fixes #628 (and #2732, which was closed as a duplicate of it).

Server Details

  • Server: git
  • Changes to: tools (git_add)

Motivation and Context

git_add used to call GitPython's repo.index.add(files). That API walks the working tree in Python instead of shelling out to git, so it knows nothing about the .git directory or .gitignore. Calling git_add with ["."] staged repository metadata, which is what the reporter saw:

modified:   ./.git/config
modified:   ./.git/index
modified:   ./.git/logs/HEAD

I reproduced this against the old implementation. The index ends up holding ./.git/HEAD, ./.git/config, ./.git/index, ./.git/logs/HEAD and every loose object. The leading ./ is the giveaway that these came from the Python tree walk rather than from git.

The underlying call was already changed to repo.git.add("--", *files) in "fix(security): bump vulnerable deps; harden git_add", so the reported behaviour no longer occurs on main. What is left is the if files == ["."] special case that was added earlier to work around it. It is redundant now, and it also skips the path validation the other branch gained.

This removes the special case so every input goes through the same validated call that delegates to git. I did not add a .git filter. Git already skips .git and honours .gitignore, and delegating matches how git_status, git_diff and the rest of the module work. There was no test covering this, so I added one to keep the index.add pattern from coming back.

How Has This Been Tested?

cd src/git && uv run pytest: 48 passed. uv run ruff check . clean, uv run pyright 0 errors.

I confirmed the new test fails for the right reason by temporarily restoring the old repo.index.add(files) body. It fails with the index containing ./.git/HEAD, ./.git/config and friends.

Checked ["."], ["./"], ["file.txt"] and [".git"] directly. The first three stage working-tree files only, and [".git"] stages nothing. Same as current main.

Breaking Changes

None. No client configuration changes needed.

Types of changes

  • Bug fix (non-breaking change which fixes an issue)

Checklist

  • I have read the MCP Protocol Documentation
  • My changes follows MCP security best practices
  • I have updated the server's README accordingly
  • I have tested this with an LLM client
  • My code follows the repository's style guidelines
  • New and existing tests pass locally
  • I have added appropriate error handling
  • I have documented all environment variables and configuration options

Additional context

If you would rather close #628 as already fixed by the earlier hardening commit, that is fair. The regression test is the part I would still want to land.

git_add kept a special case for files == ["."] that predated the switch
from repo.index.add to repo.git.add. GitPython's index.add walks the
working tree in Python and has no knowledge of the .git directory, so
it staged repository metadata as ./.git/config, ./.git/index and
./.git/logs/HEAD. Both branches now delegate to the git CLI through the
same validated path, which skips .git and honours .gitignore.

Adds a regression test asserting that staging "." never puts anything
under .git into the index.
Copilot AI balanced review requested due to automatic review settings September 12, 2026 18:33

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

.git folder staged by running 'git add .'

2 participants