{"record":{"id":"7d4a646d718a72b2","repo":"larksuite/cli","slug":"path-validation-failed","errorCode":null,"errorMessage":"path validation failed","messagePattern":"path validation failed","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"extension/fileio/errors.go","lineNumber":10,"sourceCode":"// Copyright (c) 2026 Lark Technologies Pte. Ltd.\n// SPDX-License-Identifier: MIT\n\npackage fileio\n\nimport \"errors\"\n\n// ErrPathValidation indicates the path failed security validation\n// (traversal, absolute, control chars, symlink escape, etc.).\nvar ErrPathValidation = errors.New(\"path validation failed\")\n\n// PathValidationError wraps a path validation error.\n// errors.Is(err, ErrPathValidation) returns true.\n// errors.Is(err, <original OS error>) also works via the chain.\ntype PathValidationError struct {\n\tErr error // original error\n}\n\nfunc (e *PathValidationError) Error() string { return e.Err.Error() }\nfunc (e *PathValidationError) Unwrap() []error {\n\treturn []error{ErrPathValidation, e.Err}\n}\n\n// MkdirError indicates parent directory creation failed.\n// Use errors.As(err, &fileio.MkdirError{}) to match.\ntype MkdirError struct {\n\tErr error\n}","sourceCodeStart":1,"sourceCodeEnd":28,"githubUrl":"https://github.com/larksuite/cli/blob/7fd6ef3c07182257ce776cdc5a614e122d5bd4b3/extension/fileio/errors.go#L1-L28","documentation":"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).","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\nout := filepath.Join(userInput, \"../../etc/passwd\")\nfileio.SaveResponse(ctx, resp, out)\n// after\nclean := filepath.Clean(filepath.Join(rootDir, filepath.FromSlash(userInput)))\nif !strings.HasPrefix(clean, rootDir) { return fmt.Errorf(\"path escapes root\") }\nfileio.SaveResponse(ctx, resp, clean)","handlingStrategy":"validation","validationCode":"// Go: pre-validate before calling fileio\nfunc safePath(root, p string) (string, error) {\n\tclean := filepath.Clean(filepath.Join(root, p))\n\tif !strings.HasPrefix(clean, filepath.Clean(root)+string(os.PathSeparator)) {\n\t\treturn \"\", fmt.Errorf(\"path escapes root: %s\", p)\n\t}\n\tfor _, r := range clean {\n\t\tif unicode.IsControl(r) {\n\t\t\treturn \"\", fmt.Errorf(\"control character in path\")\n\t\t}\n\t}\n\treturn clean, nil\n}","typeGuard":"func asSafePath(err error) (string, bool) {\n\tvar pve *fileio.PathValidationError\n\tif errors.As(err, &pve) && errors.Is(err, fileio.ErrPathValidation) {\n\t\treturn pve.Err.Error(), true\n\t}\n\treturn \"\", false\n}","tryCatchPattern":"// Go: classify and recover\nif err := fileio.SaveResponse(ctx, resp, out); err != nil {\n\tif errors.Is(err, fileio.ErrPathValidation) {\n\t\terr = errs.NewValidationError(errs.SubtypeInvalidArgument, \"%v\", err).WithParam(\"--output\")\n\t\t// prompt user for a corrected path and retry once\n\t}\n\treturn err\n}","preventionTips":["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."],"tags":["go","path-safety","fileio","security"],"backgroundTag":"path-validation-failed","analyzedSha":"7fd6ef3c07182257ce776cdc5a614e122d5bd4b3","analyzedAt":"2026-09-04T21:17:44.649Z","contentChangedAt":"2026-09-04T21:17:44.649Z","schemaVersion":2},"datasetVersion":"2026-09-12T02:17:10.037Z"}