flipped-aurora/gin-vue-admin · warning
file extension is not allowed
Error message
file extension is not allowed
What it means
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.
Source
Thrown at server/utils/upload/policy.go:26
var allowedUploadExtensions = map[string]struct{}{
".jpg": {}, ".jpeg": {}, ".png": {}, ".gif": {}, ".webp": {}, ".bmp": {}, ".ico": {}, ".avif": {},
".mp3": {}, ".wav": {}, ".ogg": {}, ".m4a": {}, ".flac": {}, ".aac": {},
".mp4": {}, ".webm": {}, ".mov": {}, ".avi": {}, ".mkv": {},
".txt": {}, ".md": {}, ".csv": {}, ".json": {}, ".log": {}, ".pdf": {},
".doc": {}, ".docx": {}, ".xls": {}, ".xlsx": {}, ".ppt": {}, ".pptx": {},
".zip": {}, ".rar": {}, ".7z": {}, ".tar": {}, ".gz": {}, ".tgz": {}, ".bin": {},
}
var inlineUploadExtensions = map[string]struct{}{
".jpg": {}, ".jpeg": {}, ".png": {}, ".gif": {}, ".webp": {}, ".bmp": {}, ".ico": {}, ".avif": {},
".mp3": {}, ".wav": {}, ".ogg": {}, ".m4a": {}, ".flac": {}, ".aac": {},
".mp4": {}, ".webm": {}, ".mov": {}, ".avi": {}, ".mkv": {},
}
func validatedExtension(filename string) (string, error) {
if filename == "" || strings.TrimSpace(filename) != filename || strings.ContainsAny(filename, `/\`) {
return "", errors.New("file extension is not allowed")
}
ext := strings.ToLower(filepath.Ext(filename))
if _, ok := allowedUploadExtensions[ext]; !ok {
return "", errors.New("file extension is not allowed")
}
return ext, nil
}
// ValidateFileExtension rejects active content and unknown upload types.
func ValidateFileExtension(filename string) error {
_, err := validatedExtension(filename)
return err
}
// CanServeInline limits inline responses to raster images and audio/video files.
func CanServeInline(filename string) bool {
ext, err := validatedExtension(filename)
if err != nil {View on GitHub (pinned to 3136500ef3)
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.
Example fix
// before err := upload.ValidateFileExtension(header.Filename) // "C:\fakepath\a.png" // after name := filepath.Base(strings.TrimSpace(header.Filename)) err := upload.ValidateFileExtension(name)
Defensive patterns
Strategy: validation
Validate before calling
func safeBasename(name string) (string, error) {
name = strings.TrimSpace(name)
if name == "" || strings.ContainsAny(name, `/\\`) {
return "", errors.New("invalid filename")
}
return name, nil
} Try / catch
name, err := safeBasename(header.Filename)
if err == nil {
err = upload.ValidateFileExtension(name)
}
if err != nil {
c.JSON(400, gin.H{"code": 7, "msg": "文件名或类型不被允许"})
return
} Prevention
- 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.
When it happens
Trigger: 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 \.
Common situations: 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.
Related errors
AI-assisted analysis of flipped-aurora/gin-vue-admin@3136500ef3 (2026-08-31).
Data as JSON: /api/errors/368ed440f9780f40.
Report an issue: GitHub.