AlistGo/alist · error · ErrArchiveIllegalPath

ErrArchiveIllegalPath

ErrArchiveIllegalPath

Error message

archive entry has illegal path: %s

What it means

First rejection inside SecureJoin (internal/archive/tool/securepath.go): any archive entry name containing a NUL byte (\x00) is refused with ErrArchiveIllegalPath. NUL bytes can truncate path strings in downstream OS calls, a classic path-validation bypass, so they are rejected before any normalization.

Source

Thrown at internal/archive/tool/securepath.go:19

package tool

import (
	"errors"
	"fmt"
	"os"
	"path"
	"path/filepath"
	"strings"
)

// ErrArchiveIllegalPath indicates an archive entry path is unsafe for extraction.
var ErrArchiveIllegalPath = errors.New("archive entry has illegal path")

// SecureJoin returns a safe extraction path for an archive entry.
// It rejects absolute paths, traversal, Windows drive/UNC paths, and NUL bytes.
func SecureJoin(baseDir, entryName string) (string, error) {
	if strings.Contains(entryName, "\x00") {
		return "", fmt.Errorf("%w: %s", ErrArchiveIllegalPath, entryName)
	}

	normalized := strings.ReplaceAll(entryName, "\\", "/")
	if strings.HasPrefix(normalized, "//") {
		return "", fmt.Errorf("%w: %s", ErrArchiveIllegalPath, entryName)
	}
	cleaned := path.Clean(normalized)

	if cleaned == "." || cleaned == ".." || strings.HasPrefix(cleaned, "../") {
		return "", fmt.Errorf("%w: %s", ErrArchiveIllegalPath, entryName)
	}
	if strings.HasPrefix(cleaned, "/") {
		return "", fmt.Errorf("%w: %s", ErrArchiveIllegalPath, entryName)
	}

	rel := filepath.FromSlash(cleaned)
	if filepath.IsAbs(rel) || filepath.VolumeName(rel) != "" {
		return "", fmt.Errorf("%w: %s", ErrArchiveIllegalPath, entryName)

View on GitHub (pinned to 843d9dc814)

Solutions

  1. Treat the archive as untrusted; verify its source and hash before retrying
  2. List the archive with an external tool to identify the offending member and remove/repair it
  3. Re-create the archive from trusted content rather than bypassing the check
Defensive patterns

Strategy: validation

Validate before calling

// Go: reject entry names containing NUL before calling any extraction API
func hasNULName(names []string) bool {
    for _, n := range names {
        if strings.ContainsRune(n, 0) { return true }
    }
    return false
}

Type guard

func isValidEntryName(name string) bool {
    return !strings.Contains(name, "\x00")
}

Try / catch

if err := tool.SecureJoin(outDir, name); err != nil {
    if errors.Is(err, tool.ErrArchiveIllegalPath) {
        // untrusted/corrupt archive: quarantine it; never strip NULs and retry
    }
    return err
}

Prevention

When it happens

Trigger: Extracting an archive whose member name embeds a NUL byte — typically a crafted/malicious archive (Zip-Slip variant) or a corrupted header producing embedded NULs in the decoded name.

Common situations: Deliberately malicious downloads; bit-corrupted archives; fuzz-generated files; archives produced by buggy packers that do not sanitize names.

Related errors


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