diff --git a/src/git/src/mcp_server_git/server.py b/src/git/src/mcp_server_git/server.py index 84188d8fd7..d381c8971b 100644 --- a/src/git/src/mcp_server_git/server.py +++ b/src/git/src/mcp_server_git/server.py @@ -244,7 +244,10 @@ def git_show(repo: git.Repo, revision: str) -> str: if d.diff is None: continue if isinstance(d.diff, bytes): - output.append(d.diff.decode('utf-8')) + # Git diffs can contain arbitrary file bytes. Replace malformed + # UTF-8 sequences so one binary file cannot make the whole result + # fail with UnicodeDecodeError. + output.append(d.diff.decode('utf-8', errors='replace')) else: output.append(d.diff) return "".join(output) diff --git a/src/git/tests/test_server.py b/src/git/tests/test_server.py index 893195d414..c19bb532e2 100644 --- a/src/git/tests/test_server.py +++ b/src/git/tests/test_server.py @@ -277,6 +277,18 @@ def test_git_show_initial_commit(test_repository): assert "initial commit" in result assert "test.txt" in result +def test_git_show_handles_non_utf8_diff(test_repository): + file_path = Path(test_repository.working_dir) / "binary.bin" + file_path.write_bytes(b"hello\xffworld\n") + test_repository.index.add(["binary.bin"]) + commit = test_repository.index.commit("binary diff commit") + + result = git_show(test_repository, commit.hexsha) + + assert "binary diff commit" in result + assert "binary.bin" in result + assert "hello\ufffdworld" in result + # Tests for validate_repo_path (repository scoping security fix)