From ab27b36aad15244226ceb50cdba3e300cecb70c5 Mon Sep 17 00:00:00 2001 From: LordMathis Date: Mon, 30 Sep 2024 19:31:20 +0200 Subject: [PATCH] Validate paths for static file server --- backend/cmd/server/main.go | 16 +++++++++++----- backend/internal/filesystem/filesystem.go | 18 +++++++++++------- 2 files changed, 22 insertions(+), 12 deletions(-) diff --git a/backend/cmd/server/main.go b/backend/cmd/server/main.go index e27f612..fbdfb43 100644 --- a/backend/cmd/server/main.go +++ b/backend/cmd/server/main.go @@ -58,20 +58,26 @@ func main() { api.SetupRoutes(r, database, fs) }) - // Set up static file server + // Set up static file server with path validation staticPath := os.Getenv("NOVAMD_STATIC_PATH") if staticPath == "" { staticPath = "../frontend/dist" } fileServer := http.FileServer(http.Dir(staticPath)) r.Get("/*", func(w http.ResponseWriter, r *http.Request) { - filePath := filepath.Join(staticPath, r.URL.Path) - _, err := os.Stat(filePath) + requestedPath := r.URL.Path + validatedPath, err := filesystem.ValidatePath(staticPath, requestedPath) + if err != nil { + http.Error(w, "Invalid path", http.StatusBadRequest) + return + } + + _, err = os.Stat(validatedPath) if os.IsNotExist(err) { http.ServeFile(w, r, filepath.Join(staticPath, "index.html")) return } - fileServer.ServeHTTP(w, r) + http.StripPrefix("/", fileServer).ServeHTTP(w, r) }) // Start server @@ -81,4 +87,4 @@ func main() { } log.Printf("Server starting on port %s", port) log.Fatal(http.ListenAndServe(":"+port, r)) -} +} \ No newline at end of file diff --git a/backend/internal/filesystem/filesystem.go b/backend/internal/filesystem/filesystem.go index 17db080..cf53c30 100644 --- a/backend/internal/filesystem/filesystem.go +++ b/backend/internal/filesystem/filesystem.go @@ -2,6 +2,7 @@ package filesystem import ( "errors" + "fmt" "novamd/internal/gitutils" "novamd/internal/models" "os" @@ -47,27 +48,30 @@ func (fs *FileSystem) InitializeGitRepo() error { return fs.GitRepo.EnsureRepo() } -// validatePath checks if the given path is within the root directory -func (fs *FileSystem) validatePath(path string) (string, error) { - fullPath := filepath.Join(fs.RootDir, path) +func ValidatePath(rootDir, path string) (string, error) { + fullPath := filepath.Join(rootDir, path) cleanPath := filepath.Clean(fullPath) - if !strings.HasPrefix(cleanPath, fs.RootDir) { - return "", errors.New("invalid path: outside of root directory") + if !strings.HasPrefix(cleanPath, filepath.Clean(rootDir)) { + return "", fmt.Errorf("invalid path: outside of root directory") } - relPath, err := filepath.Rel(fs.RootDir, cleanPath) + relPath, err := filepath.Rel(rootDir, cleanPath) if err != nil { return "", err } if strings.HasPrefix(relPath, "..") { - return "", errors.New("invalid path: outside of root directory") + return "", fmt.Errorf("invalid path: outside of root directory") } return cleanPath, nil } +func (fs *FileSystem) validatePath(path string) (string, error) { + return ValidatePath(fs.RootDir, path) +} + func (fs *FileSystem) ListFilesRecursively() ([]FileNode, error) { return fs.walkDirectory(fs.RootDir) }