feat: add git-explorer MCP server for read-only repository access
Implements a new MCP server that provides read-only access to git repositories using go-git. Designed for deployment verification by comparing deployed flake revisions against source repositories. 9 tools: resolve_ref, get_log, get_commit_info, get_diff_files, get_file_at_commit, is_ancestor, commits_between, list_branches, search_commits. Includes CLI commands, NixOS module, and comprehensive tests. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
57
internal/gitexplorer/validation.go
Normal file
57
internal/gitexplorer/validation.go
Normal file
@@ -0,0 +1,57 @@
|
||||
package gitexplorer
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"path/filepath"
|
||||
"slices"
|
||||
"strings"
|
||||
)
|
||||
|
||||
var (
|
||||
// ErrPathTraversal is returned when a path attempts to traverse outside the repository.
|
||||
ErrPathTraversal = errors.New("path traversal not allowed")
|
||||
// ErrAbsolutePath is returned when an absolute path is provided.
|
||||
ErrAbsolutePath = errors.New("absolute paths not allowed")
|
||||
// ErrNullByte is returned when a path contains null bytes.
|
||||
ErrNullByte = errors.New("null bytes not allowed in path")
|
||||
// ErrEmptyPath is returned when a path is empty.
|
||||
ErrEmptyPath = errors.New("path cannot be empty")
|
||||
)
|
||||
|
||||
// ValidatePath validates a file path for security.
|
||||
// It rejects:
|
||||
// - Absolute paths
|
||||
// - Paths containing null bytes
|
||||
// - Paths that attempt directory traversal (contain "..")
|
||||
// - Empty paths
|
||||
func ValidatePath(path string) error {
|
||||
if path == "" {
|
||||
return ErrEmptyPath
|
||||
}
|
||||
|
||||
// Check for null bytes
|
||||
if strings.Contains(path, "\x00") {
|
||||
return ErrNullByte
|
||||
}
|
||||
|
||||
// Check for absolute paths
|
||||
if filepath.IsAbs(path) {
|
||||
return ErrAbsolutePath
|
||||
}
|
||||
|
||||
// Clean the path and check for traversal
|
||||
cleaned := filepath.Clean(path)
|
||||
|
||||
// Check if cleaned path starts with ".."
|
||||
if strings.HasPrefix(cleaned, "..") {
|
||||
return ErrPathTraversal
|
||||
}
|
||||
|
||||
// Check for ".." components in the path
|
||||
parts := strings.Split(cleaned, string(filepath.Separator))
|
||||
if slices.Contains(parts, "..") {
|
||||
return ErrPathTraversal
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
Reference in New Issue
Block a user