{"record":{"id":"8da37ff9686b39ad","repo":"vxcontrol/pentagi","slug":"invalid-file-name","errorCode":null,"errorMessage":"invalid file name","messagePattern":"invalid file name","errorType":"validation","errorClass":null,"httpStatus":400,"severity":"error","filePath":"backend/pkg/flowfiles/files.go","lineNumber":160,"sourceCode":"\t\treturn \"\", fmt.Errorf(\"invalid path\")\n\t}\n\n\tparts := strings.Split(cleanPath, \"/\")\n\tfor i, part := range parts {\n\t\tcleanPart, err := validatePathComponent(part)\n\t\tif err != nil {\n\t\t\treturn \"\", fmt.Errorf(\"invalid path component '%s': %w\", part, err)\n\t\t}\n\t\tparts[i] = cleanPart\n\t}\n\n\treturn path.Join(parts...), nil\n}\n\nfunc validatePathComponent(component string) (string, error) {\n\tcleanName := strings.TrimSpace(component)\n\tif cleanName == \".\" || cleanName == \"..\" || cleanName == \"/\" || cleanName == \"\" {\n\t\treturn \"\", fmt.Errorf(\"invalid file name\")\n\t}\n\tif len(cleanName) > MaxFileNameLength {\n\t\treturn \"\", fmt.Errorf(\"file name is too long\")\n\t}\n\tfor _, r := range cleanName {\n\t\tif r < 0x20 || r == 0x7f {\n\t\t\treturn \"\", fmt.Errorf(\"file name contains control characters\")\n\t\t}\n\t\tswitch r {\n\t\tcase '/', '\\\\', ':', '*', '?', '\"', '<', '>', '|':\n\t\t\treturn \"\", fmt.Errorf(\"file name contains unsupported characters\")\n\t\t}\n\t}\n\n\treturn cleanName, nil\n}\n\nfunc NewFile(info os.FileInfo, sourceDir string) File {","sourceCodeStart":142,"sourceCodeEnd":178,"githubUrl":"https://github.com/vxcontrol/pentagi/blob/ea665308baaff015b226f308438a68d929d0f29b/backend/pkg/flowfiles/files.go#L142-L178","documentation":"validatePathComponent rejects a single name that is \".\", \"..\", \"/\", or empty after trimming, returning 'invalid file name'. Called directly by SanitizeFileName (a bare \".\" or \"..\" filename) and per-segment by SanitizeContainerCachePath.","triggerScenarios":"SanitizeFileName(\".\") or SanitizeFileName(\"..\"); SanitizeContainerCachePath with a segment that is \".\", \"..\", \"/\" or trims to empty (e.g. \"logs/ /x\"); tar/zip extraction names whose base is '.'.","commonSituations":"Upload requests whose multipart filename is '.'; agent tool calls passing '.' as the file name meaning 'current directory'; paths containing double slashes with whitespace between them; hidden traversal attempts like 'a/../b'.","solutions":["Supply an actual file name with at least one real character (not '.', '..', '/', or whitespace).","Strip '.'/'..' segments client-side before sending the path.","If the caller only has a directory, pass a directory-aware API path rather than using SanitizeFileName on a '.' placeholder."],"exampleFix":"// before\nname, err := flowfiles.SanitizeFileName(\"..\")\n// after\nname, err := flowfiles.SanitizeFileName(\"report.pdf\")","handlingStrategy":"validation","validationCode":"func isRealFileName(s string) bool {\n    t := strings.TrimSpace(s)\n    return t != \"\" && t != \".\" && t != \"..\" && t != \"/\"\n}","typeGuard":"func isRealFileName(s string) bool {\n    switch strings.TrimSpace(s) {\n    case \"\", \".\", \"..\", \"/\":\n        return false\n    }\n    return true\n}","tryCatchPattern":"if err != nil {\n    if err.Error() == \"invalid file name\" {\n        return fmt.Errorf(\"%q is not a usable file name\", fileName)\n    }\n    return err\n}","preventionTips":["Reject '.', '..', and empty names at the input boundary.","Never use '.' as a placeholder for 'current directory' in file APIs.","Trim whitespace before validation."],"tags":["go","filename-validation","input-validation"],"backgroundTag":"invalid-path-component","analyzedSha":"ea665308baaff015b226f308438a68d929d0f29b","analyzedAt":"2026-09-01T14:16:31.421Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}