{"record":{"id":"89d165e3d35625c2","repo":"vxcontrol/pentagi","slug":"path-exceeds-maximum-allowed-length-of-d-characte","errorCode":null,"errorMessage":"path exceeds maximum allowed length of %d characters","messagePattern":"path exceeds maximum allowed length of (.+?) characters","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"backend/pkg/resources/resources.go","lineNumber":142,"sourceCode":"\t\treturn fmt.Errorf(\"failed to delete blob %s: %w\", hash, err)\n\t}\n\treturn nil\n}\n\n// SanitizeResourcePath normalises a client-supplied virtual path and ensures it\n// is safe to use:\n//   - trims whitespace\n//   - converts backslashes to forward slashes\n//   - cleans the path (removes .., double slashes, etc.)\n//   - rejects absolute paths, dot-only components, and paths that exceed MaxPathLength\n//   - returns an error for the empty path\nfunc SanitizeResourcePath(p string) (string, error) {\n\ttrimmed := strings.TrimSpace(p)\n\tif trimmed == \"\" {\n\t\treturn \"\", fmt.Errorf(\"path must not be empty\")\n\t}\n\tif len(trimmed) > MaxPathLength {\n\t\treturn \"\", fmt.Errorf(\"path exceeds maximum allowed length of %d characters\", MaxPathLength)\n\t}\n\n\tnormalized := strings.ReplaceAll(trimmed, \"\\\\\", \"/\")\n\tif strings.HasPrefix(normalized, \"/\") {\n\t\treturn \"\", fmt.Errorf(\"path must be relative\")\n\t}\n\tfor _, part := range strings.Split(normalized, \"/\") {\n\t\tif part == \"..\" {\n\t\t\treturn \"\", fmt.Errorf(\"path must not contain parent directory traversal\")\n\t\t}\n\t}\n\tcleaned := path.Clean(\"/\" + normalized)\n\t// Remove the leading \"/\" we added for Clean, making the path relative.\n\trel := strings.TrimPrefix(cleaned, \"/\")\n\tif rel == \"\" || rel == \".\" {\n\t\treturn \"\", fmt.Errorf(\"invalid path\")\n\t}\n","sourceCodeStart":124,"sourceCodeEnd":160,"githubUrl":"https://github.com/vxcontrol/pentagi/blob/ea665308baaff015b226f308438a68d929d0f29b/backend/pkg/resources/resources.go#L124-L160","documentation":"SanitizeResourcePath (resources.go:142) enforces MaxPathLength (4096 characters) on the trimmed input. The error 'path exceeds maximum allowed length of %d characters' means the supplied path is longer than 4096 chars and is rejected before normalization to keep constructed filesystem paths within OS limits and bounded memory use.","triggerScenarios":"Passing paths longer than 4096 characters to SanitizeResourcePath via Resources, ZipResources, AddResourceFromFlow, or collectAndSanitizeResourcePaths — typically deeply nested or generated names, long upload filenames, or attacker-crafted oversized inputs.","commonSituations":"Bulk imports preserving full original directory trees; generated resource names from concatenated flow/agent IDs; malicious oversized path payloads from untrusted clients; exporting (ZipResources) a resource whose stored path grew beyond the limit.","solutions":["Truncate or shorten the path (e.g., cap the basename, hash long segments) before calling the API","Flatten deep directory structures instead of mirroring long original hierarchies","Sanitize the value at ingestion time (reject or shorten in the API handler) so bad paths never get stored","If a stored path is already too long, migrate it to a shorter generated name and update references"],"exampleFix":"// before\nsanitized, err := resources.SanitizeResourcePath(longPath) // len > 4096\n// after\nif len(strings.TrimSpace(longPath)) > resources.MaxPathLength {\n    longPath = filepath.Join(filepath.Dir(longPath)[:64], hashedName(longPath))\n}\nsanitized, err := resources.SanitizeResourcePath(longPath)","handlingStrategy":"validation","validationCode":"func pathFitsLimit(p string) bool { return len(strings.TrimSpace(p)) <= resources.MaxPathLength }","typeGuard":"func isAcceptablePath(p string) bool {\n    t := strings.TrimSpace(p)\n    return t != \"\" && len(t) <= resources.MaxPathLength && !strings.HasPrefix(strings.ReplaceAll(t, \"\\\\\", \"/\"), \"/\")\n}","tryCatchPattern":"sanitized, err := resources.SanitizeResourcePath(p)\nif err != nil {\n    var maxLen = resources.MaxPathLength\n    if strings.Contains(err.Error(), fmt.Sprintf(\"maximum allowed length of %d\", maxLen)) {\n        p = shortenPath(p, maxLen)\n        sanitized, err = resources.SanitizeResourcePath(p)\n    }\n    if err != nil { return err }\n}","preventionTips":["Validate/shorten path length at ingestion (upload handlers, import jobs) using resources.MaxPathLength","Avoid mirroring deep source directory trees; flatten or hash long segments","Set client-side max-length limits (e.g., 255 for the basename) well below 4096","Alert on oversize-path rejections to detect abusive or buggy producers early"],"tags":["validation","path","length-limit"],"backgroundTag":"path-too-long","analyzedSha":"ea665308baaff015b226f308438a68d929d0f29b","analyzedAt":"2026-09-01T14:16:31.421Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}