{"repro_id":"REPRO-2026-00076","version":3,"title":"MCP Server Git: Path Traversal via Missing Repository Path Validation","repro_type":"security","status":"published","severity":"medium","description":"In mcp-server-git versions prior to 2025.12.18, when started with --repository flag, it did not validate that repo_path arguments were within the configured path. This allows tool calls to operate on other repositories via direct paths, path traversal, or symlinks.","root_cause":"# Root Cause Analysis Report\n\n## Summary\nmcp-server-git versions prior to 2025.12.18 do not validate that the `repo_path` argument supplied to tool calls remains within the repository configured by the `--repository` flag. As a result, a client can call tools (e.g., `git_status`) against any other Git repository accessible to the server process, defeating the intended restriction.\n\n## Impact\n- **Affected component:** mcp-server-git Python package (stdio MCP server)\n- **Affected versions:** < 2025.12.18 (reproduced with 2025.11.25)\n- **Risk level:** Medium\n- **Consequence:** Clients can read or manipulate repositories outside the configured allowed repository, including via path traversal or symlink escapes.\n\n## Root Cause\nThe vulnerable server implementation directly converts `repo_path` from tool call arguments into a `Path` and opens it with `git.Repo(...)` without checking whether it is inside the configured `--repository` path. The fix (2025.12.18) introduces `validate_repo_path`, which resolves both the allowed repository and requested path (following symlinks) and rejects paths outside the allowed root before executing Git operations.\n\n## Reproduction Steps\n1. Run `repro/reproduction_steps.sh`.\n2. The script creates two Git repositories, starts the vulnerable server (2025.11.25) with `--repository` set to the allowed repo, and calls `git_status` against outside paths (direct, traversal, and symlink).\n3. The script repeats the call against the fixed server (2025.12.18) and confirms rejection.\n\n## Evidence\n- Vulnerable behavior (access outside repo succeeds):\n  - `logs/vuln_outside_repo.log` (shows `isError False` with status output for the outside repo)\n  - `logs/vuln_traversal_repo.log`\n  - `logs/vuln_symlink_repo.log`\n- Fixed behavior (access outside repo blocked):\n  - `logs/fixed_outside_repo.log`\n  - `logs/fixed_symlink_repo.log`\n- Environment: Python 3.11 with venvs created by the script, Git CLI used to initialize test repos.\n\n## Recommendations / Next Steps\n- Upgrade mcp-server-git to 2025.12.18 or later.\n- Ensure all tool entry points validate repository paths using resolved paths (including symlinks) before performing Git operations.\n- Add regression tests covering path traversal and symlink escape cases.\n\n## Additional Notes\n- `repro/reproduction_steps.sh` was executed twice successfully to verify idempotence.\n- The test covers direct path usage, relative traversal, and symlink escapes to match the fixed validation logic.\n","ghsa_id":"GHSA-j22h-9j4x-23w5","cve_id":"CVE-2025-68145","source_url":"https://github.com/modelcontextprotocol/servers/security/advisories/GHSA-j22h-9j4x-23w5","package":{"name":"mcp-server-git","ecosystem":"pip","affected_versions":"< 2025.12.18","fixed_version":"2025.12.18"},"reproduced_at":"2026-01-21T07:51:32.909781+00:00","duration_secs":689.9,"tool_calls":155,"quality":{"idempotent_verified":false,"community_verifications":0},"evidence":{"attack_vectors":["path_traversal","symlink_escape","direct_path"],"fix_mechanism":"validate_repo_path function resolves paths including symlinks before allowing operations","fixed_behavior":"isError: True - tool call blocked with Repository path is outside the allowed repository","fixed_version":"2025.12.18","vulnerability_confirmed":true,"vulnerable_behavior":"isError: False - tool call succeeds on outside repository","vulnerable_version":"2025.11.25"},"key_moments":[{"agent":"repro","description":"Agent installs mcp-server-git 2025.11.25 (vulnerable) and 2025.12.18 (fixed) in separate virtual environments for comparative testing.","index":29,"time":60000,"title":"Installing vulnerable mcp-server-git","type":"env_setup"},{"agent":"repro","description":"Agent creates two Git repositories - allowed_repo (configured path) and other_repo (outside path) to test path traversal scenarios.","index":37,"time":120000,"title":"Creating test repositories","type":"poc_created"},{"agent":"repro","description":"Agent confirms vulnerable version allows git_status calls on repositories outside the configured --repository path via direct path, ../traversal, and symlinks - all return isError: False.","index":43,"time":240000,"title":"Path traversal vulnerability confirmed","type":"vuln_triggered"},{"agent":"repro","description":"Agent confirms fixed version (2025.12.18) properly rejects all path traversal attempts with isError: True and message indicating path is outside allowed repository.","index":45,"time":280000,"title":"Fix verified","type":"confirmation"}],"published_at":"2026-01-21T07:51:35.044479+00:00","retracted":false,"artifacts":[{"path":"reproduction_steps.sh","filename":"reproduction_steps.sh","size":3751,"category":"reproduction_script"},{"path":"rca_report.md","filename":"rca_report.md","size":2481,"category":"analysis"},{"path":"path","filename":"path","size":27,"category":"other"},{"path":"ticket.md","filename":"ticket.md","size":1240,"category":"ticket"},{"path":"vuln_outside_repo.log","filename":"vuln_outside_repo.log","size":96,"category":"log"},{"path":"vuln_traversal_repo.log","filename":"vuln_traversal_repo.log","size":96,"category":"log"},{"path":"vuln_symlink_repo.log","filename":"vuln_symlink_repo.log","size":96,"category":"log"},{"path":"fixed_outside_repo.log","filename":"fixed_outside_repo.log","size":297,"category":"log"},{"path":"fixed_symlink_repo.log","filename":"fixed_symlink_repo.log","size":311,"category":"log"}]}