Billionmail/BillionMail · error

illegal file path:

Error message

illegal file path: 

What it means

During Decompress, each entry's absolute target path is checked to ensure it resolves inside the destination directory (dstAbs). If a zip entry's filename escapes that directory — the classic Zip Slip path traversal — extraction is refused with this error naming the offending entry path.

Source

Thrown at core/internal/service/compress/zip.go:194

		// remove ../ from filename
		arcName := filepath.ToSlash(filepath.Clean(fz.Name))

		if strings.Contains(arcName, "../") {
			arcName = strings.Replace(arcName, "../", "", -1)
		}

		filename := filepath.Join(dst, arcName)

		// get absolute path of the file
		filenameAbs, err := filepath.Abs(filename)

		if err != nil {
			return err
		}

		// check if the file is under the decompression target path
		if !strings.HasPrefix(filenameAbs, dstAbs) {
			return errors.New("illegal file path: " + filename)
		}

		// check if it's a directory
		// if it's a directory, create it and skip
		if fz.FileInfo().IsDir() {
			// create directory
			err = os.MkdirAll(filename, 0755)

			if err != nil {
				return err
			}

			continue
		}

		// create directory
		err = os.MkdirAll(filepath.Dir(filename), 0755)

View on GitHub (pinned to fc36c76c05)

Solutions

  1. Verify the archive contents (unzip -l) and sanitize entry names before extraction; the error is correct — do not bypass it
  2. Reject or regenerate archives from untrusted sources; validate uploads before accepting them
  3. If a legitimate relative path is falsely flagged, check for absolute entry names or symlinks in the archive and normalize before packing
  4. Ensure the destination directory itself has no trailing-separator mismatch affecting strings.HasPrefix; prefer filepath.Rel-based checks if customizing

Example fix

// malicious entry
name: "../../../../etc/cron.d/pwn" -> rejected
// after sanitizing when repacking
name: "etc/cron.d/pwn" -> extracts under dst
Defensive patterns

Strategy: validation

Validate before calling

func safeEntry(name string) bool {
    cleaned := path.Clean(name)
    return !strings.HasPrefix(cleaned, "../") && !path.IsAbs(cleaned)
}

Type guard

func isInsideDst(entry, dst string) bool {
    rel, err := filepath.Rel(dst, entry)
    return err == nil && rel != ".." && !strings.HasPrefix(rel, ".."+string(filepath.Separator))
}

Try / catch

err := z.Decompress(src, dst)
if err != nil && strings.Contains(err.Error(), "illegal file path") {
    log.Warnf("zip-slip attempt blocked: %v", err)
    return ErrUntrustedArchive
}

Prevention

When it happens

Trigger: Extracting an archive whose entry names contain traversal segments like ../ or absolute paths (e.g. ../../etc/cron.d/evil, /etc/passwd) so that filepath.Abs(filename) is not a prefix-match under the destination.

Common situations: Processing user-uploaded zip files; extracting third-party archives from untrusted sources; malicious payloads crafted for path traversal to overwrite system files.

Related errors


AI-assisted analysis of Billionmail/BillionMail@fc36c76c05 (2026-09-05). Data as JSON: /api/errors/eaf308bf99734679. Report an issue: GitHub.