Skip to content

Conversation

@olaservo
Copy link
Member

@olaservo olaservo commented Jan 4, 2026

Description

Fix a critical path traversal vulnerability and add defense-in-depth hardening:

  1. Critical: Path traversal in git_add - Allows staging files outside the repository
  2. Low (Defense-in-depth): git_create_branch hardening - Adds input validation for consistency

cc @0dd

Server Details

  • Server: git
  • Changes to: tools (git_add, git_create_branch), security validation

Motivation and Context

Path Traversal in git_add (Critical)

The git_add function uses GitPython's repo.index.add() which does not validate that file paths are within the repository, unlike the Git CLI. This allows attackers to stage sensitive files:

git_add(repo, ["../../../.ssh/id_rsa"])      # SSH keys
git_add(repo, ["../../../.kube/config"])     # K8s credentials
git_add(repo, ["../../../.aws/credentials"]) # AWS credentials

Impact: Complete credential exfiltration via git commit/push.

git_create_branch Hardening (Low - Defense-in-depth)

The git_create_branch function allowed creating branch names starting with -. While not directly exploitable (other functions like git_checkout and git_diff already reject such refs), this fix adds consistency with the existing security pattern:

git_create_branch(repo, "--help")           # Now rejected
git_create_branch(repo, "test", "--help")   # Now rejected

Impact: Prevents creating refs that could confuse other tools or future code.

How Has This Been Tested?

  • Added 14 new unit tests covering:
    • Path traversal with ../ sequences (rejected)
    • Absolute paths outside repo (rejected)
    • Specific attack vectors (~/.kube/config, ~/.ssh/id_rsa)
    • Branch names starting with - (rejected)
    • Malicious base branch names (rejected)
    • Valid operations (still allowed)
  • All existing tests pass
  • Verified exploits work without fix, fail with fix

Breaking Changes

None. Valid file paths continue to work. Only malicious paths outside the repository are now rejected with a ValueError.

Types of changes

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change)
  • Documentation update

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

These fixes follow existing security patterns in the codebase:

  • validate_repo_path() for repository boundary validation
  • Defense-in-depth checks in git_diff() and git_checkout() that reject inputs starting with -

The git_create_branch fix completes the defense-in-depth pattern across all branch-related functions.

olaservo and others added 2 commits January 4, 2026 12:59
Add validation to git_add() to ensure file paths are within the
repository boundary. This prevents attackers from staging sensitive
files outside the repo (e.g., ~/.ssh/id_rsa, ~/.kube/config) via
path traversal attacks using "../" sequences.

GitPython's repo.index.add() does not validate paths like the Git CLI
does, so explicit validation is required.

- Add validate_file_path() function to check paths are within repo
- Update git_add() to validate each file before staging
- Add comprehensive tests for path traversal prevention

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add validation to reject branch names and base branches starting with
'-' to prevent creating refs that could be interpreted as flags.

This completes the defense-in-depth pattern already used in git_diff
and git_checkout.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@0dd
Copy link
Contributor

0dd commented Jan 4, 2026

HI @olaservo

I think a more consistent way is to use https://github.com/modelcontextprotocol/servers/pull/3164/files by using repo.git.add instead of repo.index.add ensuring the consistent behavior with Git Client. This repo.git.add will respect the implementation of raw git command
https://gitpython.readthedocs.io/en/stable/quickstart.html#usage

Warning: If you experience any trouble with this, try to invoke git instead via repo.git.add(path)

@olaservo olaservo changed the title fix(git): prevent path traversal in git_add fix(git): prevent path traversal in git_add and add hardening for git_create_branch Jan 4, 2026
@olaservo olaservo closed this Jan 4, 2026
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.

2 participants