larksuite/cli · error

file provider security audit failed: %w

Error message

file provider security audit failed: %w

What it means

Before reading a secret file, the file provider runs a security audit (assertSecurePath) that rejects paths with insecure permissions, symlinks, placement outside trusted directories, or readability by other users. This error wraps the underlying audit failure. The provider is strict by default: symlinks are disallowed and AllowReadableByOthers is false.

Source

Thrown at internal/binding/secret_resolve_file.go:46

	// raw, so we mirror that resolution here before the audit — otherwise
	// an unambiguous home-relative path would be rejected by
	// requireAbsolutePath, which is meant to guard against cwd-relative
	// paths (a different concern). expandTildePath honours OPENCLAW_HOME so
	// a tilde inside an OPENCLAW_HOME-overridden config resolves to the
	// same absolute path OpenClaw itself would have used.
	targetPath := expandTildePath(pc.Path)

	// Security audit on file path
	securePath, err := AssertSecurePath(AuditParams{
		TargetPath:            targetPath,
		Label:                 "secrets.providers file path",
		TrustedDirs:           pc.TrustedDirs,
		AllowInsecurePath:     pc.AllowInsecurePath,
		AllowReadableByOthers: false, // file provider: strict by default
		AllowSymlinkPath:      false,
	})
	if err != nil {
		return "", fmt.Errorf("file provider security audit failed: %w", err)
	}

	// Read file content
	maxBytes := pc.MaxBytes
	if maxBytes <= 0 {
		maxBytes = DefaultFileMaxBytes
	}

	// Note: vfs.ReadFile loads the entire file. maxBytes is enforced post-read
	// because vfs does not expose a size-limited reader. For secret files this
	// is acceptable (default limit 1 MiB; secrets are typically < 1 KB).
	data, err := vfs.ReadFile(securePath)
	if err != nil {
		return "", fmt.Errorf("failed to read secret file %s: %w", securePath, err)
	}

	if len(data) > maxBytes {
		return "", fmt.Errorf("file provider exceeded maxBytes (%d)", maxBytes)

View on GitHub (pinned to 7fd6ef3c07)

Solutions

  1. Tighten the file permissions: `chmod 600 <secret-file>` (and `chmod 700` its parent directory).
  2. Replace the symlink with a real file, or allow symlinked paths if your threat model permits it.
  3. Add the containing directory to ProviderConfig.TrustedDirs, or set AllowInsecurePath/AllowReadableByOthers deliberately if the environment requires it.

Example fix

// before (shell)
ls -l ~/.config/myapp/secrets.json  # -rw-r--r--
// after
chmod 600 ~/.config/myapp/secrets.json
Defensive patterns

Strategy: validation

Validate before calling

info, err := os.Stat(os.ExpandEnv(p))
if err != nil { return err }
if info.Mode()&0o077 != 0 {
    return fmt.Errorf("secret file %s must be 0600, got %v", p, info.Mode().Perm())
}

Try / catch

secret, err := resolveSecretRef(ctx, ref)
if err != nil {
    var auditErr *os.PathError
    if strings.Contains(err.Error(), "security audit failed") {
        // chmod 600 the file, remove symlink, or add dir to TrustedDirs
    }
    return err
}

Prevention

When it happens

Trigger: Calling resolveSecretRef with a {source:"file"} SecretRef where the resolved path (after ~ expansion) fails assertSecurePath — e.g. the file is group/world-readable, is a symlink, lives outside TrustedDirs, or AllowInsecurePath is false and permissions are loose.

Common situations: The secret file was created with default umask 0022 making it world-readable; a dotfile manager symlinks the secrets file into place; the file lives in a directory not listed in TrustedDirs; the config copied from another machine carries different ownership.

Related errors


AI-assisted analysis of larksuite/cli@7fd6ef3c07 (2026-09-04). Data as JSON: /api/errors/f180194d365002a4. Report an issue: GitHub.