{"record":{"id":"b494aee1017ae500","repo":"siyuan-note/siyuan","slug":"marketplace-package-contains-an-unsupported-file","errorCode":null,"errorMessage":"marketplace package contains an unsupported file","messagePattern":"marketplace package contains an unsupported file","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/bazaar/local.go","lineNumber":141,"sourceCode":"\t\t\treturn err\n\t\t}\n\t}\n\treturn nil\n}\n\nfunc extractLocalPackageItem(item *zip.File, destination string, extractedTotal *uint64) error {\n\tname := strings.ReplaceAll(item.Name, \"\\\\\", \"/\")\n\tif name == \"\" || strings.HasPrefix(name, \"/\") {\n\t\treturn errors.New(\"marketplace package contains an invalid path\")\n\t}\n\tdestinationPath := filepath.Join(destination, filepath.FromSlash(name))\n\tif !gulu.File.IsSubPath(destination, destinationPath) {\n\t\treturn errors.New(\"marketplace package contains an invalid path\")\n\t}\n\n\tmode := item.Mode()\n\tif mode&os.ModeSymlink != 0 || (!mode.IsRegular() && !mode.IsDir()) {\n\t\treturn errors.New(\"marketplace package contains an unsupported file\")\n\t}\n\tif mode.IsDir() {\n\t\treturn os.MkdirAll(destinationPath, 0755)\n\t}\n\tif err := os.MkdirAll(filepath.Dir(destinationPath), 0755); err != nil {\n\t\treturn err\n\t}\n\n\tsource, err := item.Open()\n\tif err != nil {\n\t\treturn err\n\t}\n\tdefer source.Close()\n\ttarget, err := os.OpenFile(destinationPath, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0644)\n\tif err != nil {\n\t\treturn err\n\t}\n\twritten, copyErr := io.Copy(target, io.LimitReader(source, int64(maxLocalPackageFileSize)+1))","sourceCodeStart":123,"sourceCodeEnd":159,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/9f775e8a12daef8255556097396f9b2739078892/kernel/bazaar/local.go#L123-L159","documentation":"This error is thrown by extractLocalPackageItem when a zip entry of a locally uploaded marketplace package is neither a regular file nor a directory — typically a symlink (mode&os.ModeSymlink != 0) or a special file (device, fifo, etc.). The library refuses to extract such entries so a package cannot plant symlinks pointing outside the extraction directory or other dangerous node types.","triggerScenarios":"Calling ExtractLocalPackage(archivePath) with a zip that stores symlinks (common when built with `zip -y` on a project containing symlinks, or with GNU tar-converted zips) or entries with irregular modes such as setuid special files.","commonSituations":"Packaging a plugin/theme on Linux/macOS where the project contains symlinks (e.g. node_modules links, shared assets) and the zip tool preserved them; archives produced by non-zip tools with unusual entry types; malicious packages attempting symlink attacks.","solutions":["Rebuild the archive without preserving symlinks so linked content is stored as regular files: `zip -r pkg.zip .` without the -y flag (or replace symlinks with real copies first)","Find symlink entries with `unzip -l pkg.zip` (or `unzip -Z1` plus inspection) and remove or replace them in the source tree","If a symlink is required for distribution, ship the real file content instead — SiYuan marketplace packages must be self-contained","If the archive is third-party, request a repackaged version containing only regular files and directories"],"exampleFix":"// before (shell packaging preserving symlinks)\nzip -ry plugin.zip .\n\n// after\nrsync -rL --exclude node_modules ./ /tmp/stage/\n(cd /tmp/stage && zip -r ../plugin.zip .)","handlingStrategy":"validation","validationCode":"// Verify no symlinks/irregular entries before upload (Go helper)\nfunc archiveHasOnlyRegularEntries(path string) bool {\n\tr, err := zip.OpenReader(path)\n\tif err != nil { return false }\n\tdefer r.Close()\n\tfor _, f := range r.File {\n\t\tm := f.Mode()\n\t\tif m&os.ModeSymlink != 0 || (!m.IsRegular() && !m.IsDir()) {\n\t\t\treturn false\n\t\t}\n\t}\n\treturn true\n}","typeGuard":null,"tryCatchPattern":"if err := extractPackage(zipPath); err != nil {\n\tif strings.Contains(err.Error(), \"unsupported file\") {\n\t\t// instruct user to repackage without symlinks\n\t}\n}","preventionTips":["Avoid `zip -y` when packaging; let symlinks be stored as real content","Replace project symlinks with copies before packaging","Check the source tree (`find . -type l`) before building the archive"],"tags":["go","zip","symlink","security","marketplace"],"backgroundTag":"unsupported-operation","analyzedSha":"9f775e8a12daef8255556097396f9b2739078892","analyzedAt":"2026-09-19T03:17:15.984Z","contentChangedAt":"2026-09-19T03:17:15.984Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}