larksuite/cli · error
path validation failed
Error message
path validation failed
What it means
ErrPathValidation is the sentinel error in extension/fileio indicating a file path failed security validation (traversal, absolute paths, control characters, symlink escape, etc.). PathValidationError wraps it plus the original error so errors.Is matches both the sentinel and the OS cause. Callers like internal/client/response.go classify it as a typed ValidationError (SubtypeInvalidArgument, param --output).
Source
Thrown at extension/fileio/errors.go:10
// Copyright (c) 2026 Lark Technologies Pte. Ltd.
// SPDX-License-Identifier: MIT
package fileio
import "errors"
// ErrPathValidation indicates the path failed security validation
// (traversal, absolute, control chars, symlink escape, etc.).
var ErrPathValidation = errors.New("path validation failed")
// PathValidationError wraps a path validation error.
// errors.Is(err, ErrPathValidation) returns true.
// errors.Is(err, <original OS error>) also works via the chain.
type PathValidationError struct {
Err error // original error
}
func (e *PathValidationError) Error() string { return e.Err.Error() }
func (e *PathValidationError) Unwrap() []error {
return []error{ErrPathValidation, e.Err}
}
// MkdirError indicates parent directory creation failed.
// Use errors.As(err, &fileio.MkdirError{}) to match.
type MkdirError struct {
Err error
}View on GitHub (pinned to 7fd6ef3c07)
Solutions
- Sanitize the target path: make it relative to the allowed root and remove '..' segments.
- Read the wrapped original error (errors.Is/Unwrap chain) for the exact violation.
- Resolve symlinks and ensure the final path stays within the permitted root.
- Strip control characters and normalize separators before passing the path.
Example fix
// before
out := filepath.Join(userInput, "../../etc/passwd")
fileio.SaveResponse(ctx, resp, out)
// after
clean := filepath.Clean(filepath.Join(rootDir, filepath.FromSlash(userInput)))
if !strings.HasPrefix(clean, rootDir) { return fmt.Errorf("path escapes root") }
fileio.SaveResponse(ctx, resp, clean) Defensive patterns
Strategy: validation
Validate before calling
// Go: pre-validate before calling fileio
func safePath(root, p string) (string, error) {
clean := filepath.Clean(filepath.Join(root, p))
if !strings.HasPrefix(clean, filepath.Clean(root)+string(os.PathSeparator)) {
return "", fmt.Errorf("path escapes root: %s", p)
}
for _, r := range clean {
if unicode.IsControl(r) {
return "", fmt.Errorf("control character in path")
}
}
return clean, nil
} Type guard
func asSafePath(err error) (string, bool) {
var pve *fileio.PathValidationError
if errors.As(err, &pve) && errors.Is(err, fileio.ErrPathValidation) {
return pve.Err.Error(), true
}
return "", false
} Try / catch
// Go: classify and recover
if err := fileio.SaveResponse(ctx, resp, out); err != nil {
if errors.Is(err, fileio.ErrPathValidation) {
err = errs.NewValidationError(errs.SubtypeInvalidArgument, "%v", err).WithParam("--output")
// prompt user for a corrected path and retry once
}
return err
} Prevention
- Build output paths with filepath.Join under a fixed root; never concatenate raw input.
- Reject or strip '..' segments and control characters before saving.
- Resolve symlinks and verify the final path stays inside the allowed root.
- Match on fileio.ErrPathValidation with errors.Is for precise handling.
When it happens
Trigger: Calling fileio Save/open APIs (e.g. SaveResponse, wrapInputFileError paths) with a path containing '..', absolute paths when disallowed, control characters, or a symlink escaping the allowed root; classifySaveErr maps any error matching this sentinel to the typed validation error.
Common situations: Download/save targets built from untrusted input; temp-dir handling with symlinked /tmp; tests or plugins constructing paths with user data; host environment where the workspace root is a symlink.
Related errors
- unsafe --output-dir
- %s: path must be absolute, got %q
- %s: path %q is a directory, not a file
- resolve save path: %w
- Invalid column: {column!r}
AI-assisted analysis of larksuite/cli@7fd6ef3c07 (2026-09-04).
Data as JSON: /api/errors/7d4a646d718a72b2.
Report an issue: GitHub.