Skip to content

Commit 23a4bca

Browse files
committed
fix: prevent access to current directory when outside allowed directories
1 parent 6c3ff33 commit 23a4bca

File tree

1 file changed

+147
-1
lines changed

1 file changed

+147
-1
lines changed

main.go

+147-1
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,7 @@ func (s *FilesystemServer) isPathInAllowedDirs(path string) bool {
183183
}
184184
}
185185

186+
// Check if the path is within any of the allowed directories
186187
for _, dir := range s.allowedDirs {
187188
if strings.HasPrefix(absPath, dir) {
188189
return true
@@ -192,6 +193,7 @@ func (s *FilesystemServer) isPathInAllowedDirs(path string) bool {
192193
}
193194

194195
func (s *FilesystemServer) validatePath(requestedPath string) (string, error) {
196+
// Always convert to absolute path first
195197
abs, err := filepath.Abs(requestedPath)
196198
if err != nil {
197199
return "", fmt.Errorf("invalid path: %w", err)
@@ -454,7 +456,25 @@ func (s *FilesystemServer) handleReadFile(
454456
) (*mcp.CallToolResult, error) {
455457
path, ok := request.Params.Arguments["path"].(string)
456458
if !ok {
457-
return nil, fmt.Errorf("path must be a string")
459+
return nil, fmt.Errorf("path must be a string")
460+
}
461+
462+
// Handle empty or relative paths like "." or "./" by converting to absolute path
463+
if path == "." || path == "./" {
464+
// Get current working directory
465+
cwd, err := os.Getwd()
466+
if err != nil {
467+
return &mcp.CallToolResult{
468+
Content: []mcp.Content{
469+
mcp.TextContent{
470+
Type: "text",
471+
Text: fmt.Sprintf("Error resolving current directory: %v", err),
472+
},
473+
},
474+
IsError: true,
475+
}, nil
476+
}
477+
path = cwd
458478
}
459479

460480
validPath, err := s.validatePath(path)
@@ -612,6 +632,24 @@ func (s *FilesystemServer) handleWriteFile(
612632
return nil, fmt.Errorf("content must be a string")
613633
}
614634

635+
// Handle empty or relative paths like "." or "./" by converting to absolute path
636+
if path == "." || path == "./" {
637+
// Get current working directory
638+
cwd, err := os.Getwd()
639+
if err != nil {
640+
return &mcp.CallToolResult{
641+
Content: []mcp.Content{
642+
mcp.TextContent{
643+
Type: "text",
644+
Text: fmt.Sprintf("Error resolving current directory: %v", err),
645+
},
646+
},
647+
IsError: true,
648+
}, nil
649+
}
650+
path = cwd
651+
}
652+
615653
validPath, err := s.validatePath(path)
616654
if err != nil {
617655
return &mcp.CallToolResult{
@@ -706,6 +744,24 @@ func (s *FilesystemServer) handleListDirectory(
706744
return nil, fmt.Errorf("path must be a string")
707745
}
708746

747+
// Handle empty or relative paths like "." or "./" by converting to absolute path
748+
if path == "." || path == "./" {
749+
// Get current working directory
750+
cwd, err := os.Getwd()
751+
if err != nil {
752+
return &mcp.CallToolResult{
753+
Content: []mcp.Content{
754+
mcp.TextContent{
755+
Type: "text",
756+
Text: fmt.Sprintf("Error resolving current directory: %v", err),
757+
},
758+
},
759+
IsError: true,
760+
}, nil
761+
}
762+
path = cwd
763+
}
764+
709765
validPath, err := s.validatePath(path)
710766
if err != nil {
711767
return &mcp.CallToolResult{
@@ -807,6 +863,24 @@ func (s *FilesystemServer) handleCreateDirectory(
807863
return nil, fmt.Errorf("path must be a string")
808864
}
809865

866+
// Handle empty or relative paths like "." or "./" by converting to absolute path
867+
if path == "." || path == "./" {
868+
// Get current working directory
869+
cwd, err := os.Getwd()
870+
if err != nil {
871+
return &mcp.CallToolResult{
872+
Content: []mcp.Content{
873+
mcp.TextContent{
874+
Type: "text",
875+
Text: fmt.Sprintf("Error resolving current directory: %v", err),
876+
},
877+
},
878+
IsError: true,
879+
}, nil
880+
}
881+
path = cwd
882+
}
883+
810884
validPath, err := s.validatePath(path)
811885
if err != nil {
812886
return &mcp.CallToolResult{
@@ -896,6 +970,42 @@ func (s *FilesystemServer) handleMoveFile(
896970
return nil, fmt.Errorf("destination must be a string")
897971
}
898972

973+
// Handle empty or relative paths for source
974+
if source == "." || source == "./" {
975+
// Get current working directory
976+
cwd, err := os.Getwd()
977+
if err != nil {
978+
return &mcp.CallToolResult{
979+
Content: []mcp.Content{
980+
mcp.TextContent{
981+
Type: "text",
982+
Text: fmt.Sprintf("Error resolving current directory: %v", err),
983+
},
984+
},
985+
IsError: true,
986+
}, nil
987+
}
988+
source = cwd
989+
}
990+
991+
// Handle empty or relative paths for destination
992+
if destination == "." || destination == "./" {
993+
// Get current working directory
994+
cwd, err := os.Getwd()
995+
if err != nil {
996+
return &mcp.CallToolResult{
997+
Content: []mcp.Content{
998+
mcp.TextContent{
999+
Type: "text",
1000+
Text: fmt.Sprintf("Error resolving current directory: %v", err),
1001+
},
1002+
},
1003+
IsError: true,
1004+
}, nil
1005+
}
1006+
destination = cwd
1007+
}
1008+
8991009
validSource, err := s.validatePath(source)
9001010
if err != nil {
9011011
return &mcp.CallToolResult{
@@ -997,6 +1107,24 @@ func (s *FilesystemServer) handleSearchFiles(
9971107
return nil, fmt.Errorf("pattern must be a string")
9981108
}
9991109

1110+
// Handle empty or relative paths like "." or "./" by converting to absolute path
1111+
if path == "." || path == "./" {
1112+
// Get current working directory
1113+
cwd, err := os.Getwd()
1114+
if err != nil {
1115+
return &mcp.CallToolResult{
1116+
Content: []mcp.Content{
1117+
mcp.TextContent{
1118+
Type: "text",
1119+
Text: fmt.Sprintf("Error resolving current directory: %v", err),
1120+
},
1121+
},
1122+
IsError: true,
1123+
}, nil
1124+
}
1125+
path = cwd
1126+
}
1127+
10001128
validPath, err := s.validatePath(path)
10011129
if err != nil {
10021130
return &mcp.CallToolResult{
@@ -1099,6 +1227,24 @@ func (s *FilesystemServer) handleGetFileInfo(
10991227
return nil, fmt.Errorf("path must be a string")
11001228
}
11011229

1230+
// Handle empty or relative paths like "." or "./" by converting to absolute path
1231+
if path == "." || path == "./" {
1232+
// Get current working directory
1233+
cwd, err := os.Getwd()
1234+
if err != nil {
1235+
return &mcp.CallToolResult{
1236+
Content: []mcp.Content{
1237+
mcp.TextContent{
1238+
Type: "text",
1239+
Text: fmt.Sprintf("Error resolving current directory: %v", err),
1240+
},
1241+
},
1242+
IsError: true,
1243+
}, nil
1244+
}
1245+
path = cwd
1246+
}
1247+
11021248
validPath, err := s.validatePath(path)
11031249
if err != nil {
11041250
return &mcp.CallToolResult{

0 commit comments

Comments
 (0)