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

  1. Strip directories client-side and send only filepath.Base / path.basename of the original filename.
  2. Trim whitespace on the filename before validation (though note the validator rejects untrimmed input by design).
  3. Reject or sanitize names containing / or \ at the API boundary before calling the validator.
  4. 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

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.