Skip to content

[BUG] GIT_BASE_DIR rewrites absolute repo paths into cwd-dependent relative paths #43

@cyanheads

Description

@cyanheads

Summary

When GIT_BASE_DIR is set, passing an absolute repository path to a tool like git_status can be rewritten into a relative path before Git is spawned. That makes command execution depend on the MCP process cwd, which is not documented behavior for GIT_BASE_DIR.

This can surface as the generic error:

Git command not found. Please ensure Git is installed and in your PATH.

Even though Git is installed and already on PATH.

Environment

  • @cyanheads/git-mcp-server 2.10.5
  • macOS arm64
  • Git installed and available on PATH
  • Reproducible with GIT_BASE_DIR set to /Users/casey/Developer/

Reproduction

  1. Start the server with:
    • GIT_BASE_DIR=/Users/casey/Developer/
  2. Ensure the MCP process cwd is not /Users/casey/Developer (for example /code)
  3. Call git_status with an absolute repo path:
    • /Users/casey/Developer/github/pubmed-mcp-server

Actual behavior

The server logs show the absolute path being sanitized into a relative path:

  • original: /Users/casey/Developer/github/pubmed-mcp-server
  • sanitized/resolved: github/pubmed-mcp-server

That relative path is then used as the git working directory. If the process cwd is not /Users/casey/Developer, the spawn fails with ENOENT, and the server maps that to:

  • Git command not found. Please ensure Git is installed and in your PATH.

So the visible error is misleading. The real failure is that the repo path became cwd-dependent.

Expected behavior

If a client passes an absolute path that is inside GIT_BASE_DIR, the server should either:

  • preserve it as an absolute path for command execution, or
  • re-resolve the sanitized relative path against GIT_BASE_DIR before spawning Git

GIT_BASE_DIR is documented as a restriction/sandbox root, not as a requirement that the MCP process itself must also start with a matching cwd.

Why this matters

Some clients will appear to work because they happen to launch the MCP process from a compatible directory. Others will fail depending on startup cwd, even with the same tool input and same Git installation.

That makes behavior client-dependent in a way that seems unintended.

Suggested fix

After inspecting the implementation, the safest fix looks local to Git working-directory resolution, not a global sanitizer change.

Current flow:

  • sanitizePath(..., { rootDir: GIT_BASE_DIR }) returns a path relative to GIT_BASE_DIR
  • resolveWorkingDirectory() returns that relative path directly
  • Git execution then depends on the MCP process cwd

A targeted fix would be:

  • keep sanitizePath() as the bounds check / traversal guard
  • in resolveWorkingDirectory() (or immediately before Git spawn), if GIT_BASE_DIR is set, resolve the sanitized relative path back against GIT_BASE_DIR
  • pass that absolute path to the Git executor

That avoids changing sanitizer behavior for unrelated call sites.

Secondary issue

The error mapping also looks misleading. A bad resolved cwd currently gets surfaced as:

  • Git command not found. Please ensure Git is installed and in your PATH.

That should probably be distinguished from a true missing-Git case.

Related issue

Metadata

Metadata

Assignees

Labels

No labels
No labels

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions