{"record":{"id":"1c97664d06d1a208","repo":"Tencent/WeKnora","slug":"object-key-contains-path-traversal","errorCode":null,"errorMessage":"object key contains path traversal","messagePattern":"object key contains path traversal","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/utils/security.go","lineNumber":153,"sourceCode":"\tif base == \"\" || base == \".\" || base == \"..\" {\n\t\treturn \"\", fmt.Errorf(\"invalid fileName: path traversal or empty name\")\n\t}\n\tif strings.Contains(base, \"..\") {\n\t\treturn \"\", fmt.Errorf(\"invalid fileName: contains path traversal\")\n\t}\n\tif len(base) > 255 {\n\t\treturn \"\", fmt.Errorf(\"fileName too long\")\n\t}\n\treturn base, nil\n}\n\n// SafeObjectKey 校验对象存储的 key（如 COS/MinIO objectName），禁止包含 \"..\" 等路径遍历\nfunc SafeObjectKey(objectKey string) error {\n\tif objectKey == \"\" {\n\t\treturn fmt.Errorf(\"object key cannot be empty\")\n\t}\n\tif strings.Contains(objectKey, \"..\") {\n\t\treturn fmt.Errorf(\"object key contains path traversal\")\n\t}\n\treturn nil\n}\n\n// IsValidURL 验证 URL 是否安全\nfunc IsValidURL(url string) bool {\n\tif url == \"\" {\n\t\treturn false\n\t}\n\n\t// 检查长度\n\tif len(url) > 2048 {\n\t\treturn false\n\t}\n\n\t// Internal resource references are resolved through authenticated file\n\t// proxies; provider schemes remain supported for legacy stored content.\n\tallowedProtocols := []string{","sourceCodeStart":135,"sourceCodeEnd":171,"githubUrl":"https://github.com/Tencent/WeKnora/blob/988cbb03305e055d8ebb7d46d9ac6cc0803cd074/internal/utils/security.go#L135-L171","documentation":"SafeObjectKey validates object-storage keys (COS/MinIO/S3 object names) before they are used in API calls. It rejects keys containing \"..\" to prevent path-traversal attacks where a crafted key could escape its intended prefix/directory and access other objects or paths. An empty key is also rejected.","triggerScenarios":"Calling GetFile, DeleteFile, CopyFile, or GetFileURL (or parseMinioFilePath/parseS3FilePath) with an object key that contains the substring \"..\", e.g. \"../../etc/passwd\", \"a/../b\", or \"file..txt\".","commonSituations":"Building keys from user-supplied file names without sanitizing; joining paths manually with filepath.Join and not cleaning the result; legacy clients uploading keys with dot-dot segments; bugs in relative-path resolution.","solutions":["Strip or reject \"..\" segments from the key before calling the API: use path.Clean and verify the cleaned key still lies under the intended prefix","Sanitize user input: replace path separators, remove leading slashes, and reject any segment equal to \"..\"","Construct keys programmatically from safe identifiers (UUIDs, hashes) instead of raw user filenames","If \"..\" is legitimately part of a filename (e.g. \"report..v2.pdf\"), rename the object or escape/encode it"],"exampleFix":"// before\nkey := \"uploads/\" + userFilename // userFilename = \"../../secret\"\nerr := SafeObjectKey(key)\n// after\nkey := path.Clean(\"uploads/\" + strings.ReplaceAll(userFilename, \"..\", \"_\"))\nif strings.HasPrefix(key, \"uploads/\") {\n    err := SafeObjectKey(key)\n}","handlingStrategy":"validation","validationCode":"func safeKey(key string) error {\n    if key == \"\" || strings.Contains(key, \"..\") {\n        return fmt.Errorf(\"invalid object key: %q\", key)\n    }\n    return nil\n}\nif err := safeKey(userKey); err != nil { return err }","typeGuard":"func isSafeObjectKey(key string) bool {\n    return key != \"\" && !strings.Contains(key, \"..\")\n}","tryCatchPattern":"key, err := buildKey(userInput)\nif err != nil {\n    var secErr *SecurityError\n    if errors.As(err, &secErr) {\n        http.Error(w, \"invalid object key\", http.StatusBadRequest)\n        return\n    }\n    return err\n}","preventionTips":["Always pass user-supplied names through path.Clean and re-verify the prefix before forming object keys","Generate keys from server-side identifiers (UUID/hash) instead of raw filenames","Add SafeObjectKey to the earliest input-validation layer, not just at the storage call","Log-and-reject traversal attempts to detect probing"],"tags":["security","object-storage","path-traversal","validation"],"backgroundTag":"path-traversal-detected","analyzedSha":"988cbb03305e055d8ebb7d46d9ac6cc0803cd074","analyzedAt":"2026-09-02T14:41:08.344Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}