larksuite/cli · error

unsafe --output-dir

Error message

unsafe --output-dir

What it means

errOutputDirUnsafe is a sentinel error for the --output-dir flag in cmd/event/consume.go. sanitizeOutputDir rejects directories that fail path safety checks (e.g. traversal, invalid paths) and call sites wrap it as a typed errs.ValidationError (SubtypeInvalidArgument, param --output-dir) that includes the underlying reason.

Source

Thrown at cmd/event/consume.go:450

	if err != nil {
		if _, ok := errs.ProblemOf(err); ok {
			return "", err
		}
		return "", errs.NewAuthenticationError(errs.SubtypeTokenMissing,
			"resolve tenant access token: %s", err).WithCause(err)
	}
	if result == nil || result.Token == "" {
		return "", errs.NewAuthenticationError(errs.SubtypeTokenMissing,
			"no tenant access token available for app %s", appID).
			WithHint("check that app_secret is configured for this distribution")
	}
	return result.Token, nil
}

// Sentinels for errors.Is checks; call sites wrap them as typed ValidationError causes.
var (
	errInvalidParamFormat = errors.New("invalid --param format") //nolint:forbidigo // sentinel, typed at call sites
	errOutputDirUnsafe    = errors.New("unsafe --output-dir")    //nolint:forbidigo // sentinel, typed at call sites
)

func parseParams(raw []string) (map[string]string, error) {
	m := make(map[string]string)
	for _, kv := range raw {
		k, v, ok := strings.Cut(kv, "=")
		if !ok || k == "" {
			return nil, errs.NewValidationError(errs.SubtypeInvalidArgument,
				"%s %q: expected key=value", errInvalidParamFormat, kv).
				WithParam("--param").
				WithCause(errInvalidParamFormat)
		}
		m[k] = v
	}
	return m, nil
}

// watchStdinEOF drains r until EOF, writes a diagnostic, then cancels; only safe in non-TTY mode.

View on GitHub (pinned to 7fd6ef3c07)

Solutions

  1. Provide a simple, safe directory path without '..' or traversal segments (e.g. ./out or /tmp/events).
  2. Create the directory first if required and confirm you have write permission.
  3. Read the wrapped %s reason in the error to see which specific check failed.
  4. In scripts, sanitize the path (or use a fixed workspace-relative directory) before passing it.

Example fix

// before
lark event consume --output-dir ../../etc
// after
lark event consume --output-dir ./out
Defensive patterns

Strategy: validation

Validate before calling

// shell pre-check before invoking the CLI
case "$outdir" in
  *..*|""|/) echo "unsafe --output-dir: $outdir"; exit 1 ;;
esac
mkdir -p "$outdir" 2>/dev/null || { echo "cannot create $outdir"; exit 1; }

Type guard

func looksSafeOutputDir(dir string) bool {
	if dir == "" || strings.Contains(dir, "..") {
		return false
	}
	return filepath.IsAbs(dir) || strings.HasPrefix(dir, "./") || !strings.ContainsRune(dir, ':')
}

Try / catch

// Go caller of sanitizeOutputDir
safe, err := sanitizeOutputDir(dir)
if err != nil {
	if errors.Is(err, errOutputDirUnsafe) {
		// fall back to a default workspace-relative directory
		safe, err = sanitizeOutputDir("./out")
	}
	if err != nil {
		return err
	}
}

Prevention

When it happens

Trigger: Running event consume with --output-dir pointing to an unsafe path such as containing '..' traversal, an invalid/absolute path failing validation, or a path rejected by the path-safety check in sanitizeOutputDir.

Common situations: Scripts interpolating user input into the flag; relative paths that resolve outside the allowed root; copy-pasted Windows-style paths on POSIX hosts; CI templates with placeholder traversal segments.

Related errors


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