test: agregar tests completos para write_file, list_directory, append_file, delete_file
44 tests cubriendo todas las nuevas tools de archivos y la tool existente. Tests por tool: - write_file (11): crear archivo, ReadOnly, path fuera de allowed, contenido >1MB, crear dirs padre, sobreescribir, path traversal, symlink escape, deny-by-default - list_directory (9): listado plano y recursivo, limite 500 entries, symlinks fuera de allowed, path traversal, deny-by-default, no-directorio, dir vacio - append_file (11): append a existente, crear si no existe, ReadOnly, path fuera, limite 10MB total, path traversal, symlink escape, crear dirs padre - delete_file (9): borrar archivo, rechazar directorios, ReadOnly, path fuera, path traversal, symlink escape, archivo inexistente, deny-by-default Tambien corrige resolveReal() para resolver paths con multiples niveles de directorios inexistentes (necesario para MkdirAll en write/append).
This commit is contained in:
+25
-9
@@ -49,19 +49,35 @@ func validateWritePath(absPath string, allowedPaths []string, readOnly bool) err
|
||||
}
|
||||
|
||||
// resolveReal resolves symlinks for a path.
|
||||
// If the exact path doesn't exist, it resolves the deepest existing ancestor
|
||||
// and appends the remaining segments, preventing partial traversal.
|
||||
// If the exact path doesn't exist, it walks up the tree to find the deepest
|
||||
// existing ancestor, resolves its symlinks, and appends the remaining segments.
|
||||
// This prevents partial traversal attacks via symlinks in non-existent paths.
|
||||
func resolveReal(path string) (string, error) {
|
||||
real, err := filepath.EvalSymlinks(path)
|
||||
if err == nil {
|
||||
return filepath.Clean(real), nil
|
||||
}
|
||||
// Path doesn't exist — resolve parent and append base.
|
||||
parent := filepath.Dir(path)
|
||||
base := filepath.Base(path)
|
||||
realParent, err := filepath.EvalSymlinks(parent)
|
||||
if err != nil {
|
||||
return "", err
|
||||
|
||||
// Walk up to find the deepest existing ancestor.
|
||||
cleaned := filepath.Clean(path)
|
||||
var tail []string
|
||||
cur := cleaned
|
||||
for {
|
||||
parent := filepath.Dir(cur)
|
||||
tail = append([]string{filepath.Base(cur)}, tail...)
|
||||
realParent, err := filepath.EvalSymlinks(parent)
|
||||
if err == nil {
|
||||
// Found an existing ancestor — rebuild the path.
|
||||
result := realParent
|
||||
for _, seg := range tail {
|
||||
result = filepath.Join(result, seg)
|
||||
}
|
||||
return filepath.Clean(result), nil
|
||||
}
|
||||
if parent == cur {
|
||||
// Reached the root without finding an existing ancestor.
|
||||
return "", fmt.Errorf("cannot resolve any ancestor of %q", path)
|
||||
}
|
||||
cur = parent
|
||||
}
|
||||
return filepath.Clean(filepath.Join(realParent, base)), nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user