siyuan-note/siyuan · warning
invalid package name
Error message
invalid package name
What it means
getPackageInstallPath rejects marketplace package names that fail isValidPackageName before building any filesystem path. The name must be a legal directory name without path separators or '..'; this is a hardening measure against path traversal (GHSA-wr4w-7vjm-mmx3). Any install/update call with a malformed packageName fails with this error.
Solutions
- Sanitize the package name: pass only the bare directory name, without slashes or '..' segments
- If the package lives in a subdirectory, handle the base directory at the API level rather than encoding it in packageName
- Verify the source manifest's packageName is a simple identifier before calling install/update
Example fix
// before
installBazaarPackage("plugins", "acme/plugin", repoURL, hash)
// after
name := filepath.Base("acme/plugin") // "plugin"
if isValidPackageName(name) {
installBazaarPackage("plugins", name, repoURL, hash)
} Defensive patterns
Strategy: validation
Validate before calling
function isValidPackageName(name) {
return typeof name === "string" && name.length > 0 &&
!/[\\/]/.test(name) && !name.includes("..") && name === path.basename(name);
} Prevention
- Validate packageName is a bare directory name before any install/update call
- Never interpolate user or manifest paths into packageName
- Keep the GHSA-wr4w-7vjm-mmx3 advisory in mind: treat names as untrusted input
When it happens
Trigger: Calling installBazaarPackage, InstallLocalBazaarPackage, or UpdateBazaarPackage with a packageName containing '/', '\\', '..', or other characters rejected by isValidPackageName; also hit indirectly when a marketplace manifest or local package JSON supplies a hostile or malformed name.
Common situations: Installing from a hand-edited or third-party package manifest whose name field embeds a subpath (e.g. 'foo/bar'); automated scripts interpolating paths into packageName; malicious payloads probing path traversal in local-package install endpoints.
Understand the failure class
Background: Path traversal blocked: "path escapes the workspace" and "outside site root" errors when a path will not stay inside its allowed directory — this error's family across 26 libraries.
Related errors
- asset path escapes data directory
- asset path escapes data directory
- export path is outside export directory
- history path [ ] is not in workspace
- history path [ ] is not under history directory
AI-assisted analysis of siyuan-note/siyuan@9f775e8a12 (2026-09-19).
Data as JSON: /api/errors/b69e19d744f3a8ab.
Report an issue: GitHub.
Appendix: source
Thrown at kernel/model/bazaar.go:58
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 9f775e8a12)