vxcontrol/pentagi · error
file name contains control characters
Error message
file name contains control characters
What it means
validatePathComponent scans each rune and rejects components containing ASCII control characters (bytes < 0x20 or 0x7f DEL), returning 'file name contains control characters'. Control characters are illegal in most filesystems and a common path-injection vector.
Source
Thrown at backend/pkg/flowfiles/files.go:167
return "", fmt.Errorf("invalid path component '%s': %w", part, err)
}
parts[i] = cleanPart
}
return path.Join(parts...), nil
}
func validatePathComponent(component string) (string, error) {
cleanName := strings.TrimSpace(component)
if cleanName == "." || cleanName == ".." || cleanName == "/" || cleanName == "" {
return "", fmt.Errorf("invalid file name")
}
if len(cleanName) > MaxFileNameLength {
return "", fmt.Errorf("file name is too long")
}
for _, r := range cleanName {
if r < 0x20 || r == 0x7f {
return "", fmt.Errorf("file name contains control characters")
}
switch r {
case '/', '\\', ':', '*', '?', '"', '<', '>', '|':
return "", fmt.Errorf("file name contains unsupported characters")
}
}
return cleanName, nil
}
func NewFile(info os.FileInfo, sourceDir string) File {
return NewFileWithPath(info, path.Join(sourceDir, info.Name()))
}
func NewFileWithPath(info os.FileInfo, filePath string) File {
return File{
ID: ID(filePath),
Name: info.Name(),View on GitHub (pinned to ea665308ba)
Solutions
- Strip or reject control characters at the source before calling (e.g. strings.Map replacing r < 0x20 || r == 0x7f).
- Ensure filenames from terminal/log parsing are trimmed of newlines and escape sequences.
- Treat this as suspicious input: log and reject the request rather than sanitizing silently if it may be an injection attempt.
Example fix
// before
name, err := flowfiles.SanitizeFileName("log\x1b[31m.txt")
// after
cleaned := strings.Map(func(r rune) rune {
if r < 0x20 || r == 0x7f { return -1 }
return r
}, "log\x1b[31m.txt")
name, err := flowfiles.SanitizeFileName(cleaned) Defensive patterns
Strategy: validation
Validate before calling
func hasControlChars(s string) bool {
for _, r := range s {
if r < 0x20 || r == 0x7f {
return true
}
}
return false
} Type guard
func isPrintableName(s string) bool {
for _, r := range s {
if r < 0x20 || r == 0x7f {
return false
}
}
return true
} Try / catch
if err != nil {
if err.Error() == "file name contains control characters" {
return fmt.Errorf("rejecting name with control characters (possible injection)")
}
return err
} Prevention
- Strip newlines/ANSI escapes when extracting names from terminal or log output.
- Reject rather than silently clean suspicious control bytes.
- Validate names decoded from URLs (watch for %00, %0A, %0D).
When it happens
Trigger: SanitizeFileName or SanitizeContainerCachePath with a component containing \n, \r, \t, \x00, escape bytes, or DEL — e.g. filenames extracted from raw binary data, log lines with embedded newlines, or names built from untrusted terminal output.
Common situations: Agent passes a file name copied from terminal output including ANSI escape sequences or a trailing newline; uploads where the multipart filename came from a crafted HTTP client with %0A or %00; paths parsed from binary formats.
Related errors
- invalid file name
- file name contains unsupported characters
- path is required
- invalid path component '%s': %w
- file name is too long
AI-assisted analysis of vxcontrol/pentagi@ea665308ba (2026-09-01).
Data as JSON: /api/errors/3e3848b383f9e844.
Report an issue: GitHub.