larksuite/cli · error
local input path must not contain control characters
Error message
local input path must not contain control characters
What it means
LocalInputPath rejects any input path containing control characters (unicode.IsControl, plus charcheck.RejectControlChars for the dangerous set). Paths are user-controlled and get embedded in error messages and progress output, where control characters enable log injection or terminal manipulation.
Source
Thrown at internal/vfs/localfileio/path.go:65
// flags via stdin ("-").
func SafeInputPath(path string) (string, error) {
return safePath(path, "--file")
}
// LocalInputPath validates an input path in the process local filesystem
// namespace. It intentionally does not impose allowlist containment or
// canonicalize the returned path: absolute paths, parent-relative paths, and
// symlink traversal retain their normal OS semantics (the grandfathered
// apps-upload exception, see #2005). The built-in denylist still applies:
// even the relaxed tier may not reach protected directories. Character
// validation remains mandatory because paths are user-controlled and may
// appear in errors or progress output.
func LocalInputPath(path string) (string, error) {
if strings.TrimSpace(path) == "" {
return "", fmt.Errorf("local input path must not be empty")
}
if strings.IndexFunc(path, unicode.IsControl) >= 0 {
return "", fmt.Errorf("local input path must not contain control characters")
}
if err := charcheck.RejectControlChars(path, "local input path"); err != nil {
return "", err
}
if err := validateLocalInputPlatform(path); err != nil {
return "", err
}
if err := denyCheckLocalInput(path); err != nil {
return "", err
}
return path, nil
}
// denyCheckLocalInput applies the built-in denylist to the relaxed local
// input tier. Resolution is fail-closed like safePath, but the allowlist is
// deliberately not consulted here. This tier hands the path back verbatim, so
// every interpretation of it is checked — the caller opens the one the OS
// picks, which for "~/..." is a literal "~" entry in the working directory.View on GitHub (pinned to 7fd6ef3c07)
Solutions
- Trim/strip control characters from the path before passing it, e.g. strings.TrimFunc(p, unicode.IsControl) for leading/trailing \r\n
- Fix the producer: read lines with a scanner that strips line terminators instead of raw splitting
- Quote/sanitize any external input before placing it in a path; reject values containing \x00 or escape chars
- If the filename legitimately contains a control character, rename the file
Example fix
// before p, err := localfileio.LocalInputPath(line) // line came from strings.Split(data, "\n") // after line = strings.TrimSpace(line) p, err := localfileio.LocalInputPath(line)
Defensive patterns
Strategy: validation
Validate before calling
if strings.IndexFunc(p, unicode.IsControl) >= 0 {
return fmt.Errorf("path %q contains control characters", p)
} Type guard
func safePathChars(p string) bool {
return strings.IndexFunc(p, unicode.IsControl) < 0 && !strings.ContainsRune(p, 0)
} Try / catch
p, err := localfileio.LocalInputPath(flagValue)
if err != nil {
return fmt.Errorf("--file: %w", err)
} Prevention
- Trim line terminators when reading paths from files or lists
- Sanitize external/pasted input before using it in paths
- Reject or escape values containing \x00 and escape sequences early
When it happens
Trigger: Calling localfileio.LocalInputPath with a path containing \n, \r, \t, \x1b, \x00, or other control code points — typically from unparsed multi-line input, split errors, or tampered configuration.
Common situations: A file list read with line endings left in each entry (CRLF not trimmed); data pasted from a PDF/chat into a script; a config value containing escape sequences; malicious input attempting log injection.
Related errors
- %s contains invalid control characters
- invalid profile name %q: contains control characters
- local input path must not be empty
- %s: %w
- %s must be an absolute path, got %q
AI-assisted analysis of larksuite/cli@7fd6ef3c07 (2026-09-04).
Data as JSON: /api/errors/4219ff0562b1397f.
Report an issue: GitHub.