{"record":{"id":"72a0947ad63299b0","repo":"kovidgoyal/kitty","slug":"abs-target-w","errorCode":null,"errorMessage":"abs target: %w","messagePattern":"abs target: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"tools/utils/paths.go","lineNumber":361,"sourceCode":"//     whether the returned relative path escapes the base directory.\n//   - On Windows behaviour is consistent with filepath semantics.\nfunc RelativeIfUnder(base, target string, resolveSymlinks bool) (rel string, inside bool, err error) {\n\t// Optionally resolve symlinks first\n\tif resolveSymlinks {\n\t\tif base, err = filepath.EvalSymlinks(base); err != nil {\n\t\t\treturn \"\", false, fmt.Errorf(\"resolving base symlinks: %w\", err)\n\t\t}\n\t\tif target, err = filepath.EvalSymlinks(target); err != nil {\n\t\t\treturn \"\", false, fmt.Errorf(\"resolving target symlinks: %w\", err)\n\t\t}\n\t}\n\n\t// Make absolute and clean\n\tif base, err = filepath.Abs(base); err != nil {\n\t\treturn \"\", false, fmt.Errorf(\"abs base: %w\", err)\n\t}\n\tif target, err = filepath.Abs(target); err != nil {\n\t\treturn \"\", false, fmt.Errorf(\"abs target: %w\", err)\n\t}\n\n\t// On Windows the volume (drive letter) must match. If they don't, the path is not inside.\n\tif runtime.GOOS == \"windows\" {\n\t\tif !strings.EqualFold(filepath.VolumeName(base), filepath.VolumeName(target)) {\n\t\t\treturn \"\", false, nil\n\t\t}\n\t}\n\n\t// Get the relative path from base to target\n\trel, err = filepath.Rel(base, target)\n\tif err != nil {\n\t\treturn \"\", false, fmt.Errorf(\"computing relative path: %w\", err)\n\t}\n\n\t// If rel begins with \"..\" (or is \"..\"), then target is outside base.\n\t// Use os.PathSeparator to be portable.\n\tup := \"..\" + string(os.PathSeparator)","sourceCodeStart":343,"sourceCodeEnd":379,"githubUrl":"https://github.com/kovidgoyal/kitty/blob/6d5d0c440603ad9bdf6dcd599f73f6dde21acb44/tools/utils/paths.go#L343-L379","documentation":"RelativeIfUnder makes the target absolute with filepath.Abs after symlink resolution. Like the base variant, it only fails when os.Getwd fails (deleted/unreadable working directory) while resolving a relative target. The wrapped error distinguishes the exact cause.","triggerScenarios":"Relative target path plus a process CWD that has been deleted or is unreadable; sandboxed runtimes blocking getwd.","commonSituations":"Tool invoked with relative file arguments from a directory that later disappears; containers where WORKDIR was removed at runtime.","solutions":["Convert targets to absolute paths before calling (filepath.Abs at argument-parse time).","Re-run from a valid working directory.","Avoid holding relative paths across long-running operations; normalize early.","Handle the error and prompt the user to re-supply the path."],"exampleFix":"// before\nrel, inside, err := utils.RelativeIfUnder(base, relTarget, false)\n// after\nabsTarget, _ := filepath.Abs(relTarget)\nrel, inside, err := utils.RelativeIfUnder(base, absTarget, false)","handlingStrategy":"validation","validationCode":"target, _ = filepath.Abs(target) // resolve while CWD is still valid\nrel, inside, err := utils.RelativeIfUnder(base, target, false)","typeGuard":null,"tryCatchPattern":"rel, inside, err := utils.RelativeIfUnder(base, target, false)\nif err != nil {\n    if _, gerr := os.Getwd(); gerr != nil {\n        return fmt.Errorf(\"CWD unavailable for relative target %q: %w\", target, err)\n    }\n}","preventionTips":["Abs() all user-supplied relative paths at parse time.","Avoid chdir'ing into directories that may be removed.","Restart tools launched from since-deleted directories."],"tags":["go","filesystem","cwd","paths"],"backgroundTag":"path-resolution-failed","analyzedSha":"6d5d0c440603ad9bdf6dcd599f73f6dde21acb44","analyzedAt":"2026-08-27T14:20:20.142Z","schemaVersion":2},"datasetVersion":"2026-08-27T19:17:21.184Z"}