larksuite/cli · error

unsafe %s %q: %w

Error message

unsafe %s %q: %w

What it means

The extra root CA file (CLI_CA_PATH) passed binding.AssertSecurePath: it is absolute but unsafe — e.g. permissions too open in the wrong direction, symlink issues, or located in a disallowed location. The CLI wraps the underlying security-audit error with 'unsafe %s %q: %w' and refuses to load the CA.

Source

Thrown at internal/transport/tls_ca.go:35

)

// applyExtraRootCA augments t with an additional PEM bundle used for configured proxy
// TLS interception.
func applyExtraRootCA(t *http.Transport, caPath string) error {
	caPath = strings.TrimSpace(caPath)
	if caPath == "" {
		return nil
	}
	if !filepath.IsAbs(caPath) {
		return fmt.Errorf("invalid %s %q: must be an absolute path to a PEM file", envvars.CliCAPath, caPath)
	}
	safeCAPath, err := binding.AssertSecurePath(binding.AuditParams{
		TargetPath:            caPath,
		Label:                 envvars.CliCAPath,
		AllowReadableByOthers: true,
	})
	if err != nil {
		return fmt.Errorf("unsafe %s %q: %w", envvars.CliCAPath, caPath, err)
	}
	pemBytes, err := vfs.ReadFile(safeCAPath)
	if err != nil {
		return fmt.Errorf("failed to read %s %q: %w", envvars.CliCAPath, caPath, err)
	}

	// Augment the system trust store. Do NOT silently discard a SystemCertPool
	// error: falling back to an empty pool would make this transport trust ONLY
	// the extra CA (dropping all system roots), which narrows trust unexpectedly
	// and could break TLS to legitimate endpoints. Fail closed instead.
	pool, err := x509.SystemCertPool()
	if err != nil {
		return fmt.Errorf("failed to load system cert pool for %s: %w", envvars.CliCAPath, err)
	}
	if pool == nil {
		pool = x509.NewCertPool()
	}
	if ok := pool.AppendCertsFromPEM(pemBytes); !ok {

View on GitHub (pinned to 7fd6ef3c07)

Solutions

  1. Inspect the wrapped cause (%w) to see which security check failed.
  2. Move the CA file to a dedicated root-owned directory such as /etc/lark-cli/ with 0644 perms and no symlinks.
  3. Re-run with the new absolute path in CLI_CA_PATH.
Defensive patterns

Strategy: validation

Validate before calling

fi, err := os.Lstat(caPath)
if err != nil || fi.Mode()&os.ModeSymlink != 0 {
	return fmt.Errorf("CA path must be a regular, non-symlinked file")
}

Try / catch

if err := applyExtraRootCA(tr, caPath); err != nil {
	var secErr *binding.SecurityError
	if errors.As(err, &secErr) {
		log.Fatalf("CA path rejected by security policy: %v", secErr)
	}
	return err
}

Prevention

When it happens

Trigger: CLI_CA_PATH points to a file that fails AssertSecurePath — symlinked path, path under a world-writable directory, or other policy violation — while AllowReadableByOthers is requested; raised in ApplyToTransport -> applyExtraRootCA.

Common situations: CA bundle placed in /tmp or another shared directory; symlink chains created for convenience; hardened environments where file ownership is root but the CLI runs unprivileged.

Related errors


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