flipped-aurora/gin-vue-admin · warning

%s 文件名不合法

Error message

%s 文件名不合法

What it means

Unzip rejects archive entries whose names contain ".." to prevent Zip Slip path traversal, returning "%s 文件名不合法" with the offending entry name. Without this check, a crafted zip could write files outside destDir. It is a security guard executed for every entry before extraction.

Source

Thrown at server/utils/zip.go:23

	"fmt"
	"io"
	"os"
	"path/filepath"
	"strings"
)

// 解压
func Unzip(zipFile string, destDir string) ([]string, error) {
	zipReader, err := zip.OpenReader(zipFile)
	var paths []string
	if err != nil {
		return []string{}, err
	}
	defer zipReader.Close()

	for _, f := range zipReader.File {
		if strings.Contains(f.Name, "..") {
			return []string{}, fmt.Errorf("%s 文件名不合法", f.Name)
		}
		fpath := filepath.Join(destDir, f.Name)
		paths = append(paths, fpath)
		if f.FileInfo().IsDir() {
			os.MkdirAll(fpath, os.ModePerm)
		} else {
			if err = os.MkdirAll(filepath.Dir(fpath), os.ModePerm); err != nil {
				return []string{}, err
			}

			inFile, err := f.Open()
			if err != nil {
				return []string{}, err
			}
			defer inFile.Close()

			outFile, err := os.OpenFile(fpath, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, f.Mode())
			if err != nil {

View on GitHub (pinned to 3136500ef3)

Solutions

  1. Reject or sanitize the offending archive: inspect entry names with `unzip -l` / archive tool and remove entries containing "..".
  2. Re-create the archive with clean, destination-relative entry paths and re-upload.
  3. If you control the source, generate zips with paths relative to the archive root only.
  4. Scan untrusted uploads for path traversal entries before extraction.

Example fix

// before
paths, err := ziputil.Unzip("evil.zip", dest) // contains ../../secret

// after
if zipContainsTraversal("evil.zip") { // pre-check entry names for ".."
    return errors.New("archive rejected: path traversal entry")
}
paths, err := ziputil.Unzip("evil.zip", dest)
Defensive patterns

Strategy: validation

Validate before calling

func zipHasTraversal(zipPath string) (bool, error) {
    r, err := zip.OpenReader(zipPath)
    if err != nil { return false, err }
    defer r.Close()
    for _, f := range r.File {
        if strings.Contains(f.Name, "..") {
            return true, nil
        }
    }
    return false, nil
}

Try / catch

paths, err := ziputil.Unzip(zipPath, destDir)
if err != nil {
    if strings.Contains(err.Error(), "文件名不合法") {
        return fmt.Errorf("archive rejected: unsafe entry path (possible zip slip): %w", err)
    }
    return err
}

Prevention

When it happens

Trigger: Calling Unzip(zipPath, destDir) on an archive containing any entry whose f.Name includes ".." (e.g. "../../etc/passwd" or "a/../b"), produced intentionally or by archives created with absolute/relative parent paths.

Common situations: Processing user-uploaded zips (a classic Zip Slip attack vector); archives generated on Windows with backslash/.. segments; legacy tooling that zips with parent-relative paths; accepting untrusted archive uploads without scanning.

Related errors


AI-assisted analysis of flipped-aurora/gin-vue-admin@3136500ef3 (2026-08-31). Data as JSON: /api/errors/9564b88ae55bbab5. Report an issue: GitHub.