{"record":{"id":"368ed440f9780f40","repo":"flipped-aurora/gin-vue-admin","slug":"file-extension-is-not-allowed","errorCode":null,"errorMessage":"file extension is not allowed","messagePattern":"file extension is not allowed","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"server/utils/upload/policy.go","lineNumber":26,"sourceCode":"\nvar allowedUploadExtensions = map[string]struct{}{\n\t\".jpg\": {}, \".jpeg\": {}, \".png\": {}, \".gif\": {}, \".webp\": {}, \".bmp\": {}, \".ico\": {}, \".avif\": {},\n\t\".mp3\": {}, \".wav\": {}, \".ogg\": {}, \".m4a\": {}, \".flac\": {}, \".aac\": {},\n\t\".mp4\": {}, \".webm\": {}, \".mov\": {}, \".avi\": {}, \".mkv\": {},\n\t\".txt\": {}, \".md\": {}, \".csv\": {}, \".json\": {}, \".log\": {}, \".pdf\": {},\n\t\".doc\": {}, \".docx\": {}, \".xls\": {}, \".xlsx\": {}, \".ppt\": {}, \".pptx\": {},\n\t\".zip\": {}, \".rar\": {}, \".7z\": {}, \".tar\": {}, \".gz\": {}, \".tgz\": {}, \".bin\": {},\n}\n\nvar inlineUploadExtensions = map[string]struct{}{\n\t\".jpg\": {}, \".jpeg\": {}, \".png\": {}, \".gif\": {}, \".webp\": {}, \".bmp\": {}, \".ico\": {}, \".avif\": {},\n\t\".mp3\": {}, \".wav\": {}, \".ogg\": {}, \".m4a\": {}, \".flac\": {}, \".aac\": {},\n\t\".mp4\": {}, \".webm\": {}, \".mov\": {}, \".avi\": {}, \".mkv\": {},\n}\n\nfunc validatedExtension(filename string) (string, error) {\n\tif filename == \"\" || strings.TrimSpace(filename) != filename || strings.ContainsAny(filename, `/\\`) {\n\t\treturn \"\", errors.New(\"file extension is not allowed\")\n\t}\n\text := strings.ToLower(filepath.Ext(filename))\n\tif _, ok := allowedUploadExtensions[ext]; !ok {\n\t\treturn \"\", errors.New(\"file extension is not allowed\")\n\t}\n\treturn ext, nil\n}\n\n// ValidateFileExtension rejects active content and unknown upload types.\nfunc ValidateFileExtension(filename string) error {\n\t_, err := validatedExtension(filename)\n\treturn err\n}\n\n// CanServeInline limits inline responses to raster images and audio/video files.\nfunc CanServeInline(filename string) bool {\n\text, err := validatedExtension(filename)\n\tif err != nil {","sourceCodeStart":8,"sourceCodeEnd":44,"githubUrl":"https://github.com/flipped-aurora/gin-vue-admin/blob/3136500ef380842b0eb6c4daa87c3f8a47fcf9e0/server/utils/upload/policy.go#L8-L44","documentation":"The upload-policy validator rejects the filename itself before even looking at the extension: the name is empty, has leading/trailing whitespace, or contains a path separator (/ or \\). This is an application-level guard against path traversal and sneaky names; it deliberately reuses the generic 'file extension is not allowed' message to avoid leaking validation details.","triggerScenarios":"Calling upload.ValidateFileExtension (or CanServeInline) with: \"\" (empty), \" report.pdf\" or \"report.pdf \" (untrimmed whitespace), \"a/b.png\", \"a\\\\b.png\", \"../x.txt\" — any name containing / or \\.","commonSituations":"Frontend passing a fakepath-like string (\"C:\\\\fakepath\\\\img.png\") instead of just the basename, filenames copied with trailing spaces from emails or macOS Finder, attackers probing path traversal in upload endpoints.","solutions":["Strip directories client-side and send only filepath.Base / path.basename of the original filename.","Trim whitespace on the filename before validation (though note the validator rejects untrimmed input by design).","Reject or sanitize names containing / or \\ at the API boundary before calling the validator.","Return a clearer 400 message from your handler so users know to fix the filename."],"exampleFix":"// before\nerr := upload.ValidateFileExtension(header.Filename) // \"C:\\fakepath\\a.png\"\n// after\nname := filepath.Base(strings.TrimSpace(header.Filename))\nerr := upload.ValidateFileExtension(name)","handlingStrategy":"validation","validationCode":"func safeBasename(name string) (string, error) {\n    name = strings.TrimSpace(name)\n    if name == \"\" || strings.ContainsAny(name, `/\\\\`) {\n        return \"\", errors.New(\"invalid filename\")\n    }\n    return name, nil\n}","typeGuard":null,"tryCatchPattern":"name, err := safeBasename(header.Filename)\nif err == nil {\n    err = upload.ValidateFileExtension(name)\n}\nif err != nil {\n    c.JSON(400, gin.H{\"code\": 7, \"msg\": \"文件名或类型不被允许\"})\n    return\n}","preventionTips":["Always reduce multipart filenames to their basename before validation.","Trim whitespace client-side as well as server-side.","Never trust raw client filenames for storage paths.","Return a distinct 400 message so users can correct the filename."],"tags":["validation","upload","filename","security"],"backgroundTag":"invalid-upload-filename","analyzedSha":"3136500ef380842b0eb6c4daa87c3f8a47fcf9e0","analyzedAt":"2026-08-31T13:50:02.721Z","schemaVersion":2},"datasetVersion":"2026-08-31T19:17:28.585Z"}