{"record":{"id":"0d3390248099f41f","repo":"larksuite/cli","slug":"s-cannot-stat-q-w-0d3390","errorCode":null,"errorMessage":"%s: cannot stat %q: %w","messagePattern":"(.+?): cannot stat %q: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/binding/audit_unix.go","lineNumber":20,"sourceCode":"// SPDX-License-Identifier: MIT\n\n//go:build !windows\n\npackage binding\n\nimport (\n\t\"fmt\"\n\t\"os\"\n\t\"syscall\"\n\n\t\"github.com/larksuite/cli/internal/vfs\"\n)\n\n// checkOwnerUID verifies the file is owned by the current user.\nfunc checkOwnerUID(path, label string) error {\n\tstat, err := vfs.Stat(path)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"%s: cannot stat %q: %w\", label, path, err)\n\t}\n\tsysStat, ok := stat.Sys().(*syscall.Stat_t)\n\tif !ok {\n\t\treturn fmt.Errorf(\"%s: cannot retrieve file owner for %q\", label, path)\n\t}\n\tif sysStat.Uid != uint32(os.Getuid()) {\n\t\treturn fmt.Errorf(\"%s: path %q is owned by uid %d, expected %d\",\n\t\t\tlabel, path, sysStat.Uid, os.Getuid())\n\t}\n\treturn nil\n}\n\n// auditFilePermissions rejects world/group-writable modes (always) and\n// world/group-readable modes (unless allowReadableByOthers is true, which\n// exec commands typically need for their usual 755 mode).\nfunc auditFilePermissions(effectivePath string, allowReadableByOthers bool, label string) error {\n\tinfo, err := vfs.Stat(effectivePath)\n\tif err != nil {","sourceCodeStart":2,"sourceCodeEnd":38,"githubUrl":"https://github.com/larksuite/cli/blob/7fd6ef3c07182257ce776cdc5a614e122d5bd4b3/internal/binding/audit_unix.go#L2-L38","documentation":"checkOwnerUID verifies that the audited file is owned by the current OS user; it first calls vfs.Stat on the effective path. If that stat fails (file vanished between the symlink resolution and this step, permission denied on a parent directory, or the file is on an unavailable mount), the error is wrapped and returned. Owner checks exist so a file another user controls cannot be injected into secret/command resolution.","triggerScenarios":"Stat fails during the ownership check after symlink resolution and permission audit succeeded: file deleted concurrently, parent directory lost search permission, path on a dead network mount, or the effective path differs subtly (case, trailing whitespace) from the real file.","commonSituations":"Script removed by a cleanup job while lark-cli runs; config path referencing a file under /root while running as a normal user; NFS/autofs home directories dropped offline; a mis-typed path that only partially matches the real filename.","solutions":["Check the wrapped cause: ENOENT means the file is gone — recreate it or fix the config path to an existing file","EACCES/EPERM: verify execute/search permission on every parent directory for the current user","Confirm the volume holding the file is mounted (df /path; mount output)","Re-run the command to rule out a transient TOCTOU race"],"exampleFix":"// before: path under root while running as alice\ncfg.path = \"/root/secrets-tool.sh\"\n// after\ncfg.path = \"/home/alice/bin/secrets-tool.sh\"; chmod 700 /home/alice/bin/secrets-tool.sh","handlingStrategy":"validation","validationCode":"if _, err := os.Stat(resolvedPath); err != nil {\n  return fmt.Errorf(\"pre-flight: cannot access %s: %w\", resolvedPath, err)\n}","typeGuard":null,"tryCatchPattern":"_, err := binding.AssertSecurePath(params)\nif err != nil {\n  var perr *fs.PathError\n  if errors.As(err, &perr) {\n    switch {\n    case errors.Is(perr.Err, syscall.ENOENT): // restore file or fix path\n    case errors.Is(perr.Err, syscall.EACCES): // fix parent dir permissions\n    }\n  }\n  return err\n}","preventionTips":["Verify the file exists with ls -l before configuring it","Use absolute paths of real files, not near-miss spellings","Keep the file on a mounted, local-reachable volume","Avoid running the CLI while cleanup jobs may delete the file"],"tags":["filesystem","stat","permissions","security-audit"],"backgroundTag":"file-not-found","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"}