larksuite/cli · error
%s: path %q is owned by uid %d, expected %d
Error message
%s: path %q is owned by uid %d, expected %d
What it means
The security audit requires that the audited file is owned by the user running lark-cli. If the file's UID (read from syscall.Stat_t) differs from os.Getuid(), checkOwnerUID throws this error so a file controlled by another account (root, another team member, a service user) cannot be bound into secrets or command resolution — another owner could silently replace its contents.
Source
Thrown at internal/binding/audit_unix.go:27
"fmt"
"os"
"syscall"
"github.com/larksuite/cli/internal/vfs"
)
// checkOwnerUID verifies the file is owned by the current user.
func checkOwnerUID(path, label string) error {
stat, err := vfs.Stat(path)
if err != nil {
return fmt.Errorf("%s: cannot stat %q: %w", label, path, err)
}
sysStat, ok := stat.Sys().(*syscall.Stat_t)
if !ok {
return fmt.Errorf("%s: cannot retrieve file owner for %q", label, path)
}
if sysStat.Uid != uint32(os.Getuid()) {
return fmt.Errorf("%s: path %q is owned by uid %d, expected %d",
label, path, sysStat.Uid, os.Getuid())
}
return nil
}
// auditFilePermissions rejects world/group-writable modes (always) and
// world/group-readable modes (unless allowReadableByOthers is true, which
// exec commands typically need for their usual 755 mode).
func auditFilePermissions(effectivePath string, allowReadableByOthers bool, label string) error {
info, err := vfs.Stat(effectivePath)
if err != nil {
return fmt.Errorf("%s: cannot stat %q: %w", label, effectivePath, err)
}
mode := info.Mode().Perm()
if mode&0o002 != 0 {
return fmt.Errorf("%s: path %q is world-writable (mode %04o)", label, effectivePath, mode)
}View on GitHub (pinned to 7fd6ef3c07)
Solutions
- chown the file to your user: sudo chown $(id -u):$(id -g) <path> (if policy allows)
- Copy the file so you become the owner: cp <path> ~/bin/tool && chmod 700 ~/bin/tool, then point config at your copy
- Re-install the tool into your user space so files are created with your uid
- If the other-owner file is intentional, use the option that sets AllowInsecurePath — accepting the risk explicitly
- Fix NFS uid mapping (root_squash/anonuid settings) if the mismatch comes from the mount
Example fix
// before -rwxr--r-- root root /opt/tool/bin/agent.sh # owned by root, run as alice // after sudo chown alice:alice /opt/tool/bin/agent.sh # or cp to ~/bin and chown there
Defensive patterns
Strategy: validation
Validate before calling
if st, err := os.Stat(path); err == nil {
if sys, ok := st.Sys().(*syscall.Stat_t); ok && int(sys.Uid) != os.Getuid() {
return fmt.Errorf("%s owned by uid %d, run as %d", path, sys.Uid, os.Getuid())
}
} Prevention
- chown audited files to the user running the CLI
- Install personal tools into user space, not root-owned system paths
- Fix uid mapping on NFS mounts; avoid root-created bind-mount files
- Re-check ownership after provisioning/CI jobs that create files as root
When it happens
Trigger: AssertSecurePath (without AllowInsecurePath) audits a file whose owner UID != current uid: file installed by root (e.g. system-wide install with root ownership), files copied from a tarball preserving another uid, or shared workstations where a colleague created the file.
Common situations: Script deployed by puppet/ansible as root but executed by a normal user; scp/tar transfers preserving uid 0; files created inside containers as root and used from a bind mount by a non-root host user; NFS with uid mapping mismatch (squash_all / anonuid).
Related errors
- %s: path %q is world-writable (mode %04o)
- %s: path %q is group-writable (mode %04o)
- %s: cannot stat %q: %w
- keychain access blocked
- %s: cannot resolve symlink %q: %w
AI-assisted analysis of larksuite/cli@7fd6ef3c07 (2026-09-04).
Data as JSON: /api/errors/4d7aac797ea444be.
Report an issue: GitHub.