AlistGo/alist · error · ErrArchiveIllegalPath

ErrArchiveIllegalPath

ErrArchiveIllegalPath

Error message

archive entry has illegal path: %s

What it means

Security guard in the generic archives decompressor (Archives.Decompress walking an extracted fs.FS directory tree). After SecureJoin resolves the destination, each entry's FileInfo mode is checked; any non-regular, non-directory entry — symlink, device, FIFO — is rejected with the ErrArchiveIllegalPath sentinel. This blocks archive members that would otherwise write special files or escape via links during extraction.

Source

Thrown at internal/archive/archives/archives.go:149

			relPath := strings.TrimPrefix(p, path+"/")
			if relPath == "" || relPath == "." {
				if d.IsDir() {
					return nil
				}
			}
			dstPath, err := tool.SecureJoin(outputPath, relPath)
			if err != nil {
				return err
			}
			if d.IsDir() {
				return os.MkdirAll(dstPath, 0700)
			}
			info, err := d.Info()
			if err != nil {
				return err
			}
			if !info.Mode().IsRegular() {
				return fmt.Errorf("%w: %s", tool.ErrArchiveIllegalPath, p)
			}
			if err := os.MkdirAll(filepath.Dir(dstPath), 0700); err != nil {
				return err
			}
			return decompress(fsys, p, dstPath, func(_ float64) {}, limiter)
		})
	} else {
		entryName := stdpath.Base(path)
		dstPath, e := tool.SecureJoin(outputPath, entryName)
		if e != nil {
			return e
		}
		if err = os.MkdirAll(filepath.Dir(dstPath), 0700); err != nil {
			return err
		}
		err = decompress(fsys, path, dstPath, up, limiter)
	}
	return filterPassword(err)

View on GitHub (pinned to 843d9dc814)

Solutions

  1. Confirm the archive actually needs the special entries; re-create it with symlinks dereferenced (e.g. tar -h / zip --symlinks off)
  2. Extract such archives with a system tool that supports preserving special files instead of the built-in decompressor
  3. If you control the archive producer, package regular files only
  4. Do not remove the check — it is a deliberate Zip-Slip/special-file defense

Example fix

# before: archive contains symlinks
tar czf bundle.tgz mydir/   # mydir has symlinks

# after: dereference symlinks when packing
tar czfhs bundle.tgz mydir/
Defensive patterns

Strategy: validation

Validate before calling

// Go: pre-walk the archive fs and reject/flag non-regular entries before extracting
func hasSpecialEntries(fsys fs.FS) (bool, error) {
    bad := false
    err := fs.WalkDir(fsys, ".", func(p string, d fs.DirEntry, err error) error {
        if err != nil { return err }
        if d.IsDir() { return nil }
        info, err := d.Info(); if err != nil { return err }
        if !info.Mode().IsRegular() { bad = true }
        return nil
    })
    return bad, err
}

Type guard

func isSafeArchiveEntry(info fs.FileInfo) bool {
    return info.Mode().IsRegular() || info.IsDir()
}

Try / catch

// Go: sentinel check with errors.Is, skip-and-continue instead of aborting
if err := archivesTool.Decompress(ss, out, args, up); err != nil {
    if errors.Is(err, tool.ErrArchiveIllegalPath) {
        // refuse or quarantine the archive; do not retry with the same input
    }
}

Prevention

When it happens

Trigger: Decompressing an archive (zip/tar/etc. handled via the archives tool) whose inner directory contains a symlink, hardlink, char/block device, or FIFO entry, when the user extracts a folder (InnerPath resolves to a directory and fs.WalkDir runs).

Common situations: Linux-created tarballs preserving symlinks; macOS app bundles with symlinks; malicious or unusual archives containing device nodes; extracting system backup archives.

Related errors


AI-assisted analysis of AlistGo/alist@843d9dc814 (2026-08-15). Data as JSON: /api/errors/94bfbbe81d68f4c9. Report an issue: GitHub.