Tencent/WeKnora · error
invalid file path: %w
Error message
invalid file path: %w
What it means
GetFile wraps the error from secutils.SafePathUnderBase when the requested filePath does not resolve to a location inside the storage base directory. This is the path-traversal guard: paths like '../secrets.txt' or absolute paths outside baseDir are rejected before any file is opened. The wrapped error explains which path check failed.
Source
Thrown at internal/application/service/file/local.go:118
logger.Infof(ctx, "File saved successfully: %s", filePath)
// Return provider:// path format: local://{relative_path}
relPath, _ := filepath.Rel(s.baseDir, filePath)
return localScheme + filepath.ToSlash(relPath), nil
}
// GetFile retrieves a file from the local file system by its path
// Returns a ReadCloser for reading the file content
// Supports both provider scheme: local://{relative_path} and legacy absolute paths.
// 路径必须在 baseDir 下,防止路径遍历(如 ../../)
func (s *localFileService) GetFile(ctx context.Context, filePath string) (io.ReadCloser, error) {
logger.Infof(ctx, "Getting file: %s", filePath)
candidate := s.normalizePathForBase(filePath)
resolved, err := secutils.SafePathUnderBase(s.baseDir, candidate)
if err != nil {
logger.Errorf(ctx, "Path traversal denied for GetFile: %v", err)
return nil, fmt.Errorf("invalid file path: %w", err)
}
file, err := os.Open(resolved)
if err != nil {
// baseDir/resolved are logged so a storage base-dir mismatch (e.g.
// writer and reader started with different LOCAL_STORAGE_BASE_DIR)
// is immediately visible instead of just "no such file or directory".
logger.Errorf(ctx, "Failed to open file: baseDir=%s resolvedPath=%s err=%v", s.baseDir, resolved, err)
return nil, fmt.Errorf("failed to open file: %w", err)
}
logger.Info(ctx, "File opened successfully")
return file, nil
}
// DeleteFile removes a file from the local file system
// Returns an error if deletion fails
// 路径必须在 baseDir 下,防止路径遍历(如 ../../)View on GitHub (pinned to 988cbb0330)
Solutions
- Remove '..' segments and ensure the stored path is relative to baseDir before calling GetFile
- Verify the record was written by the same local service with the same LOCAL_STORAGE_BASE_DIR (provider scheme must be local://)
- Decode/sanitize URL-encoded paths before lookup and reject suspicious input at the API boundary
- Use the returned local:// path from SaveFile rather than constructing paths manually
Example fix
// before: unsafe, raw user input
f, err := svc.GetFile(ctx, r.URL.Query().Get("path"))
// after: validate the path shape first
p := r.URL.Query().Get("path")
if strings.Contains(p, "..") || filepath.IsAbs(p) {
http.Error(w, "invalid path", http.StatusBadRequest)
return
}
f, err := svc.GetFile(ctx, p) Defensive patterns
Strategy: validation
Validate before calling
func safeLocalPath(p string) bool {
if strings.Contains(p, "..") || filepath.IsAbs(p) {
return false
}
if i := strings.Index(p, "://"); i >= 0 && p[:i+3] != "local://" {
return false
}
return true
} Type guard
func isLocalPath(p string) bool {
return !filepath.IsAbs(p) && !strings.Contains(p, "..")
} Try / catch
file, err := svc.GetFile(ctx, path)
if err != nil {
if errors.Is(err, secutils.ErrPathTraversal) {
http.Error(w, "invalid path", http.StatusBadRequest)
return
}
http.Error(w, "internal error", http.StatusInternalServerError)
} Prevention
- Never pass raw user input as a storage path; use paths returned by SaveFile
- Decode URL-encoded input before validation
- Keep LOCAL_STORAGE_BASE_DIR consistent across writer and reader instances
- Pen-test traversal patterns (../, %2e%2e, symlinks) in CI
When it happens
Trigger: Calling GetFile with a path containing '..' segments that escape baseDir, an absolute path pointing outside baseDir, a different-provider scheme (e.g. s3://...) reaching the local service, or a symlink trick that resolves outside the base.
Common situations: Storing raw client-supplied filenames and passing them straight to GetFile; storage rows containing paths written by a different backend or with a different LOCAL_STORAGE_BASE_DIR; URL-encoded traversal (%2e%2e%2f) not decoded before validation.
Related errors
- invalid path: %w
- invalid source path: %w
- invalid file name: %w
- invalid source path: %w
- invalid file path: %w
AI-assisted analysis of Tencent/WeKnora@988cbb0330 (2026-09-02).
Data as JSON: /api/errors/1b7cd8471d1fd64d.
Report an issue: GitHub.