siyuan-note/siyuan · error

invalid package name

Error message

invalid package name

What it means

Thrown by getPackageInstallPath when bazaar.IsValidPackageName(packageName) returns false. The validator rejects names that are empty, longer than 255 chars, start/end with dot or space, contain '..', contain characters outside 0x20-0x7E, contain any of <>&'":/\|?*, or match a reserved OS name (CON, PRN, NUL, etc.). This is a path-traversal and cross-platform-safety guard referenced by GHSA-wr4w-7vjm-mmx3.

Source

Thrown at kernel/model/bazaar.go:57

	Pkg     *bazaar.Package
	DirName string
}

// UpdatedPackage 描述本地已安装包及其在线可用更新
type UpdatedPackage struct {
	Installed *bazaar.Package `json:"installed"`
	Available *bazaar.Package `json:"available"`
}

func isValidPackageName(packageName string) bool {
	return bazaar.IsValidPackageName(packageName)
}

func getPackageInstallPath(pkgType, packageName string) (string, string, error) {
	// 校验包名必须是合法的目录名,不能包含路径分隔符或 ..,防止路径遍历
	// https://github.com/siyuan-note/siyuan/security/advisories/GHSA-wr4w-7vjm-mmx3
	if !isValidPackageName(packageName) {
		return "", "", errors.New("invalid package name")
	}

	var baseDir, jsonFileName string
	switch pkgType {
	case "plugins":
		baseDir, jsonFileName = filepath.Join(util.DataDir, "plugins"), "plugin.json"
	case "themes":
		baseDir, jsonFileName = util.ThemesPath, "theme.json"
	case "icons":
		baseDir, jsonFileName = util.IconsPath, "icon.json"
	case "templates":
		baseDir, jsonFileName = filepath.Join(util.DataDir, "templates"), "template.json"
	case "widgets":
		baseDir, jsonFileName = filepath.Join(util.DataDir, "widgets"), "widget.json"
	default:
		logging.LogErrorf("invalid package type: %s", pkgType)
		return "", "", errors.New("invalid package type")
	}

View on GitHub (pinned to 251596fc0d)

Solutions

  1. Pass the package name exactly as declared in its manifest (plugin.json/theme.json) — a plain directory-safe identifier.
  2. Strip leading/trailing whitespace and reject names with separators before calling install APIs.
  3. If the name comes from user input, validate it with IsValidPackageName before forwarding to the kernel.

Example fix

// before
name := userInput // "../escape"
// after
name := strings.TrimSpace(userInput)
if !bazaar.IsValidPackageName(name) {
    return fmt.Errorf("invalid package name")
}
Defensive patterns

Strategy: validation

Validate before calling

// Validate before any install/uninstall/size call.
if !bazaar.IsValidPackageName(packageName) {
    return fmt.Errorf("invalid package name: %q", packageName)
}

Type guard

func isValidPkgName(s string) bool {
    return bazaar.IsValidPackageName(s)
}

Prevention

When it happens

Trigger: Any install/update/uninstall path-size call passing a packageName containing a path separator, '..', a Windows reserved name, or non-ASCII/special characters. Reached from InstallBazaarPackage, InstallLocalBazaarPackage, UpdateBazaarPackage, getPackageUninstallPath, and GetInstalledPackageSize.

Common situations: Malformed request from a plugin/extension sending a directory-style name, a crafted name from a malicious package manifest, or a frontend bug passing an empty/space-padded name. Also blocks any attempt to escape the package base directory.

Related errors


AI-assisted analysis of siyuan-note/siyuan@251596fc0d (2026-08-12). Data as JSON: /api/errors/b69e19d744f3a8ab. Report an issue: GitHub.