{"record":{"id":"b69e19d744f3a8ab","repo":"siyuan-note/siyuan","slug":"invalid-package-name","errorCode":null,"errorMessage":"invalid package name","messagePattern":"invalid package name","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/model/bazaar.go","lineNumber":57,"sourceCode":"\tPkg     *bazaar.Package\n\tDirName string\n}\n\n// UpdatedPackage 描述本地已安装包及其在线可用更新\ntype UpdatedPackage struct {\n\tInstalled *bazaar.Package `json:\"installed\"`\n\tAvailable *bazaar.Package `json:\"available\"`\n}\n\nfunc isValidPackageName(packageName string) bool {\n\treturn bazaar.IsValidPackageName(packageName)\n}\n\nfunc getPackageInstallPath(pkgType, packageName string) (string, string, error) {\n\t// 校验包名必须是合法的目录名，不能包含路径分隔符或 ..，防止路径遍历\n\t// https://github.com/siyuan-note/siyuan/security/advisories/GHSA-wr4w-7vjm-mmx3\n\tif !isValidPackageName(packageName) {\n\t\treturn \"\", \"\", errors.New(\"invalid package name\")\n\t}\n\n\tvar baseDir, jsonFileName string\n\tswitch pkgType {\n\tcase \"plugins\":\n\t\tbaseDir, jsonFileName = filepath.Join(util.DataDir, \"plugins\"), \"plugin.json\"\n\tcase \"themes\":\n\t\tbaseDir, jsonFileName = util.ThemesPath, \"theme.json\"\n\tcase \"icons\":\n\t\tbaseDir, jsonFileName = util.IconsPath, \"icon.json\"\n\tcase \"templates\":\n\t\tbaseDir, jsonFileName = filepath.Join(util.DataDir, \"templates\"), \"template.json\"\n\tcase \"widgets\":\n\t\tbaseDir, jsonFileName = filepath.Join(util.DataDir, \"widgets\"), \"widget.json\"\n\tdefault:\n\t\tlogging.LogErrorf(\"invalid package type: %s\", pkgType)\n\t\treturn \"\", \"\", errors.New(\"invalid package type\")\n\t}","sourceCodeStart":39,"sourceCodeEnd":75,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/251596fc0de2f9528c00c224252fd073a99973f4/kernel/model/bazaar.go#L39-L75","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Pass the package name exactly as declared in its manifest (plugin.json/theme.json) — a plain directory-safe identifier.","Strip leading/trailing whitespace and reject names with separators before calling install APIs.","If the name comes from user input, validate it with IsValidPackageName before forwarding to the kernel."],"exampleFix":"// before\nname := userInput // \"../escape\"\n// after\nname := strings.TrimSpace(userInput)\nif !bazaar.IsValidPackageName(name) {\n    return fmt.Errorf(\"invalid package name\")\n}","handlingStrategy":"validation","validationCode":"// Validate before any install/uninstall/size call.\nif !bazaar.IsValidPackageName(packageName) {\n    return fmt.Errorf(\"invalid package name: %q\", packageName)\n}","typeGuard":"func isValidPkgName(s string) bool {\n    return bazaar.IsValidPackageName(s)\n}","tryCatchPattern":null,"preventionTips":["Pass package names exactly as declared in the package manifest.","Validate user-supplied names with IsValidPackageName before forwarding to kernel APIs.","Never construct package names from path segments or free-form input."],"tags":["bazaar","package-management","path-traversal","input-validation","security"],"backgroundTag":null,"analyzedSha":"251596fc0de2f9528c00c224252fd073a99973f4","analyzedAt":"2026-08-12T21:18:37.123Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}