{"record":{"id":"5069cc749f42403b","repo":"larksuite/cli","slug":"exec-provider-security-audit-failed-w","errorCode":null,"errorMessage":"exec provider security audit failed: %w","messagePattern":"exec provider security audit failed: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/binding/secret_resolve_exec.go","lineNumber":81,"sourceCode":"\n// prepareExecRun audits the command path, marshals the JSON request,\n// assembles the minimal child env, and resolves timeout / output limits.\n// Never spawns a process — the returned execRun is pure data.\nfunc prepareExecRun(ref *SecretRef, providerName string, pc *ProviderConfig, getenv func(string) string) (*execRun, error) {\n\tif pc.Command == \"\" {\n\t\treturn nil, fmt.Errorf(\"exec provider command is empty\")\n\t}\n\n\tsecurePath, err := AssertSecurePath(AuditParams{\n\t\tTargetPath:            pc.Command,\n\t\tLabel:                 \"exec provider command\",\n\t\tTrustedDirs:           pc.TrustedDirs,\n\t\tAllowInsecurePath:     pc.AllowInsecurePath,\n\t\tAllowReadableByOthers: true, // exec commands are typically 755\n\t\tAllowSymlinkPath:      pc.AllowSymlinkCommand,\n\t})\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"exec provider security audit failed: %w\", err)\n\t}\n\n\treqJSON, err := marshalExecRequest(ref, providerName)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\ttimeoutMs, maxOut := effectiveExecLimits(pc)\n\treturn &execRun{\n\t\tPath:    securePath,\n\t\tArgs:    pc.Args,\n\t\tEnv:     buildExecEnv(pc, getenv),\n\t\tRequest: reqJSON,\n\t\tTimeout: time.Duration(timeoutMs) * time.Millisecond,\n\t\tMaxOut:  maxOut,\n\t}, nil\n}\n","sourceCodeStart":63,"sourceCodeEnd":99,"githubUrl":"https://github.com/larksuite/cli/blob/7fd6ef3c07182257ce776cdc5a614e122d5bd4b3/internal/binding/secret_resolve_exec.go#L63-L99","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"# before (script world-writable)\nls -l /tmp/resolver.sh  # -rwxrwxrwx\n\n# after\nchmod 755 /opt/resolver.sh\n# config\ncommand: /opt/resolver.sh\ntrusted-dirs: [\"/opt\"]","handlingStrategy":"validation","validationCode":"// pre-check the command path like the audit does\ninfo, err := os.Stat(p.Command)\nif err != nil { return fmt.Errorf(\"command %s not found\", p.Command) }\nif info.Mode()&0o022 != 0 {\n    return fmt.Errorf(\"command %s must not be group/other-writable (chmod 755)\", p.Command)\n}\nfor _, d := range trustedDirs {\n    if strings.HasPrefix(p.Command, d+string(os.PathSeparator)) { return nil }\n}\nreturn fmt.Errorf(\"command %s is outside trusted-dirs\", p.Command)","typeGuard":null,"tryCatchPattern":"secret, err := resolveSecretRef(ctx, ref)\nif err != nil {\n    var auditErr *SecurityAuditError\n    if errors.As(err, &auditErr) { // or match on the wrapped cause\n        log.Fatalf(\"fix exec command path: %v (chmod/chown, move into trusted-dirs, or allow symlink)\", auditErr)\n    }\n    return err\n}","preventionTips":["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"],"tags":["security","exec","path-validation"],"backgroundTag":"insecure-executable-path","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"}