{"record":{"id":"4c2959729b083e41","repo":"vxcontrol/pentagi","slug":"invalid-path-component-s-w","errorCode":null,"errorMessage":"invalid path component '%s': %w","messagePattern":"invalid path component '(.+?)': %w","errorType":"validation","errorClass":null,"httpStatus":400,"severity":"error","filePath":"backend/pkg/flowfiles/files.go","lineNumber":149,"sourceCode":"}\n\nfunc SanitizeContainerCachePath(containerPath string) (string, error) {\n\ttrimmedPath := strings.TrimSpace(containerPath)\n\tif trimmedPath == \"\" {\n\t\treturn \"\", fmt.Errorf(\"path is required\")\n\t}\n\n\tnormalizedPath := strings.ReplaceAll(trimmedPath, \"\\\\\", \"/\")\n\tcleanPath := strings.TrimPrefix(path.Clean(\"/\"+normalizedPath), \"/\")\n\tif cleanPath == \".\" || cleanPath == \"\" {\n\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\")","sourceCodeStart":131,"sourceCodeEnd":167,"githubUrl":"https://github.com/vxcontrol/pentagi/blob/ea665308baaff015b226f308438a68d929d0f29b/backend/pkg/flowfiles/files.go#L131-L167","documentation":"After normalization, SanitizeContainerCachePath splits the path on '/' and runs each component through validatePathComponent. This error wraps the per-component failure, identifying the offending component (e.g. one containing '..', an unsupported character, or being too long) with the underlying reason.","triggerScenarios":"Any path segment that fails validatePathComponent: a segment equal to \".\" or \"..\" (e.g. \"logs/../../etc/passwd\"), a segment containing one of : * ? \" < > | (e.g. \"C:file\", \"a*b.txt\"), a segment longer than 255 bytes, an empty segment after cleaning (e.g. \"a//b\" yields no empty split parts, but \"a/ /b\" has a component \" \" that trims to empty), or a segment with control characters.","commonSituations":"Agent-generated paths containing glob characters like *.log; Windows drive-letter prefixes (\"C:\\\\Users\" → component \"C:\"); base64 or binary junk with control bytes; paths built by naive string concatenation producing '..' segments.","solutions":["Read the wrapped component and reason in the message, then correct that specific segment in the source of the path.","Reject or re-ask the agent/user when the path contains '..', ':', '*', '?', '\"', '<', '>', '|', backslashes (converted to '/' but still disallowed inside a single segment), or control characters.","Pre-validate with the same rules before calling: split the normalized path and check each segment for length ≤255 and absence of forbidden characters."],"exampleFix":"// before\npullFiles(containerPath: \"logs/../../etc/passwd\")\n// after\npullFiles(containerPath: \"logs/app.log\")","handlingStrategy":"validation","validationCode":"func prevalidatePath(p string) error {\n    for _, part := range strings.Split(strings.ReplaceAll(p, \"\\\\\", \"/\"), \"/\") {\n        if part == \".\" || part == \"..\" || strings.TrimSpace(part) == \"\" {\n            return fmt.Errorf(\"bad component %q\", part)\n        }\n        if len(part) > 255 {\n            return fmt.Errorf(\"component %q too long\", part)\n        }\n        for _, r := range part {\n            if r < 0x20 || r == 0x7f {\n                return fmt.Errorf(\"control char in %q\", part)\n            }\n            if strings.ContainsRune(\"/:*?\\\"<>|\", r) && r != '/' {\n                return fmt.Errorf(\"unsupported char %q in %q\", r, part)\n            }\n        }\n    }\n    return nil\n}","typeGuard":"func isSafeComponent(s string) bool {\n    return s != \".\" && s != \"..\" && s != \"\" && len(s) <= 255 &&\n        !strings.ContainsAny(s, \"/:*?\\\"<>|\")\n}","tryCatchPattern":"if err != nil {\n    if strings.HasPrefix(err.Error(), \"invalid path component\") {\n        var comp string\n        fmt.Sscanf(err.Error(), \"invalid path component '%s':\", &comp)\n        return fmt.Errorf(\"bad segment %q in container path\", comp)\n    }\n    return err\n}","preventionTips":["Validate each path segment before sending it to the backend.","Strip Windows drive-letter prefixes and glob characters.","Keep paths relative and free of '..' segments."],"tags":["go","path-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"}