1
0
mirror of https://github.com/tw93/Mole.git synced 2026-03-22 18:30:08 +00:00

security: validate raw path in moveToTrash before filepath.Abs resolves traversal

filepath.Abs resolves ".." components, so the existing validatePath call
on the resolved path could never catch traversal attempts. Move validation
before Abs to reject raw input with "..", keeping the post-Abs check as
defense-in-depth.
This commit is contained in:
Tw93
2026-03-14 10:39:33 +08:00
parent ba01cb7f43
commit 9db5488397
2 changed files with 18 additions and 1 deletions

View File

@@ -122,12 +122,17 @@ func trashPathWithProgress(root string, counter *int64) (int64, error) {
// moveToTrash uses macOS Finder to move a file/directory to Trash.
// This is the safest method as it uses the system's native trash mechanism.
func moveToTrash(path string) error {
// Validate raw input before Abs resolves ".." components away.
if err := validatePath(path); err != nil {
return err
}
absPath, err := filepath.Abs(path)
if err != nil {
return fmt.Errorf("failed to resolve path: %w", err)
}
// Validate path to prevent path traversal attacks.
// Validate resolved path as well (defense-in-depth).
if err := validatePath(absPath); err != nil {
return err
}

View File

@@ -5,6 +5,7 @@ package main
import (
"os"
"path/filepath"
"strings"
"testing"
)
@@ -82,6 +83,17 @@ func TestMoveToTrashNonExistent(t *testing.T) {
}
}
func TestMoveToTrashRejectsTraversal(t *testing.T) {
// Verify the full production path rejects ".." before filepath.Abs resolves it.
err := moveToTrash("/tmp/fakedir/../../../etc/passwd")
if err == nil {
t.Fatal("expected error for path with traversal components")
}
if !strings.Contains(err.Error(), "traversal") {
t.Fatalf("expected traversal error, got: %v", err)
}
}
func TestValidatePath(t *testing.T) {
tests := []struct {
name string