larksuite/cli · error
exec provider security audit failed: %w
Error message
exec provider security audit failed: %w
What it means
prepareExecRun runs AssertSecurePath to audit the exec provider's command path (ownership, permissions, symlink policy, trusted dirs). When that audit fails, the error is wrapped with this message and returned, refusing to execute an untrusted binary. This protects against running a command that could be tampered with by another user.
Source
Thrown at internal/binding/secret_resolve_exec.go:81
// prepareExecRun audits the command path, marshals the JSON request,
// assembles the minimal child env, and resolves timeout / output limits.
// Never spawns a process — the returned execRun is pure data.
func prepareExecRun(ref *SecretRef, providerName string, pc *ProviderConfig, getenv func(string) string) (*execRun, error) {
if pc.Command == "" {
return nil, fmt.Errorf("exec provider command is empty")
}
securePath, err := AssertSecurePath(AuditParams{
TargetPath: pc.Command,
Label: "exec provider command",
TrustedDirs: pc.TrustedDirs,
AllowInsecurePath: pc.AllowInsecurePath,
AllowReadableByOthers: true, // exec commands are typically 755
AllowSymlinkPath: pc.AllowSymlinkCommand,
})
if err != nil {
return nil, fmt.Errorf("exec provider security audit failed: %w", err)
}
reqJSON, err := marshalExecRequest(ref, providerName)
if err != nil {
return nil, err
}
timeoutMs, maxOut := effectiveExecLimits(pc)
return &execRun{
Path: securePath,
Args: pc.Args,
Env: buildExecEnv(pc, getenv),
Request: reqJSON,
Timeout: time.Duration(timeoutMs) * time.Millisecond,
MaxOut: maxOut,
}, nil
}
View on GitHub (pinned to 7fd6ef3c07)
Solutions
- Inspect the wrapped cause (%w) for the exact path violation and fix the file permissions/ownership (e.g. chmod 755, chown to the running user)
- Move the command into a directory listed in the provider's trusted-dirs config, or add the command's directory to trusted-dirs
- If the command is intentionally a symlink, set allow-symlink-command (AllowSymlinkCommand) to true in the provider config
- Verify the command path exists at runtime — a stale path also fails the audit
Example fix
# before (script world-writable) ls -l /tmp/resolver.sh # -rwxrwxrwx # after chmod 755 /opt/resolver.sh # config command: /opt/resolver.sh trusted-dirs: ["/opt"]
Defensive patterns
Strategy: validation
Validate before calling
// pre-check the command path like the audit does
info, err := os.Stat(p.Command)
if err != nil { return fmt.Errorf("command %s not found", p.Command) }
if info.Mode()&0o022 != 0 {
return fmt.Errorf("command %s must not be group/other-writable (chmod 755)", p.Command)
}
for _, d := range trustedDirs {
if strings.HasPrefix(p.Command, d+string(os.PathSeparator)) { return nil }
}
return fmt.Errorf("command %s is outside trusted-dirs", p.Command) Try / catch
secret, err := resolveSecretRef(ctx, ref)
if err != nil {
var auditErr *SecurityAuditError
if errors.As(err, &auditErr) { // or match on the wrapped cause
log.Fatalf("fix exec command path: %v (chmod/chown, move into trusted-dirs, or allow symlink)", auditErr)
}
return err
} Prevention
- Install resolver executables in a root-owned or user-owned dedicated dir (e.g. /usr/local/bin or /opt) and include it in trusted-dirs
- Never place exec-provider commands in /tmp or shared/writable mounts
- Keep permissions at 755 (not 777); if the command is a symlink, explicitly enable allow-symlink-command
- Re-check path ownership after deploys, container builds, or CI checkouts that may rewrite permissions
When it happens
Trigger: resolveExecRef -> prepareExecRun calls AssertSecurePath and the command path fails the audit: it lives outside TrustedDirs, is writable by others/group when it shouldn't be, is a symlink when AllowSymlinkCommand is false, is world-readable-insecure, or the path doesn't exist.
Common situations: Placing the resolver script in a world-writable directory like /tmp or a shared mount; the command is a symlink into a dev directory; the binary's permissions were loosened (e.g. 777 after chmod mishap); running on a machine where the trusted-dirs config doesn't include the install location; CI checkout makes the script writable by the CI user only but the audit expects stricter ownership.
Related errors
- %s: path must be absolute, got %q
- %s: cannot stat %q: %w
- %s: path %q is a directory, not a file
- %s: path %q is a symlink (not allowed)
- unsafe output path: %w
AI-assisted analysis of larksuite/cli@7fd6ef3c07 (2026-09-04).
Data as JSON: /api/errors/5069cc749f42403b.
Report an issue: GitHub.