{"record":{"id":"02a0f3e3ed567b73","repo":"siyuan-note/siyuan","slug":"marketplace-package-contains-a-file-that-is-too-la","errorCode":null,"errorMessage":"marketplace package contains a file that is too large","messagePattern":"marketplace package contains a file that is too large","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/bazaar/local.go","lineNumber":106,"sourceCode":"\nfunc extractLocalPackageArchive(archivePath, destination string) error {\n\treader, err := zip.OpenReader(archivePath)\n\tif err != nil {\n\t\treturn errors.New(\"invalid marketplace package archive\")\n\t}\n\tdefer reader.Close()\n\n\tif len(reader.File) == 0 {\n\t\treturn errors.New(\"marketplace package archive is empty\")\n\t}\n\tif len(reader.File) > maxLocalPackageFileCount {\n\t\treturn errors.New(\"marketplace package contains too many files\")\n\t}\n\n\tvar declaredTotal uint64\n\tfor _, item := range reader.File {\n\t\tif item.UncompressedSize64 > maxLocalPackageFileSize {\n\t\t\treturn errors.New(\"marketplace package contains a file that is too large\")\n\t\t}\n\t\tif ^uint64(0)-declaredTotal < item.UncompressedSize64 {\n\t\t\treturn errors.New(\"marketplace package is too large\")\n\t\t}\n\t\tdeclaredTotal += item.UncompressedSize64\n\t\tif declaredTotal > maxLocalPackageExtractSize {\n\t\t\treturn errors.New(\"marketplace package is too large\")\n\t\t}\n\t}\n\n\tif err = os.MkdirAll(destination, 0755); err != nil {\n\t\treturn err\n\t}\n\tvar extractedTotal uint64\n\tfor _, item := range reader.File {\n\t\tif err = extractLocalPackageItem(item, destination, &extractedTotal); err != nil {\n\t\t\treturn err\n\t\t}","sourceCodeStart":88,"sourceCodeEnd":124,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/251596fc0de2f9528c00c224252fd073a99973f4/kernel/bazaar/local.go#L88-L124","documentation":"A single zip entry declares an UncompressedSize64 greater than maxLocalPackageFileSize (256 MiB). Thrown in the first pass of extractLocalPackageArchive (kernel/bazaar/local.go:105-106) using the header's declared size, before any bytes are actually decompressed. It is a per-file cap independent of the overall archive size.","triggerScenarios":"ExtractLocalPackage processes an archive where at least one entry's zip header reports an uncompressed size over 256 MiB. Common with bundled videos, model files, large datasets, or prebuilt binaries.","commonSituations":"A plugin bundles a large binary asset (ML model, video, image atlas); a theme ships uncompressed high-res artwork; a malicious archive spoofs a huge declared size.","solutions":["Identify the oversized entry with `unzip -lv <path>` and remove or shrink it","Compress or downsample large media before packaging","Split oversized assets out of the marketplace package and load them at runtime instead"],"exampleFix":"// before: bundling a 300MB video into the zip\nzip -r pkg.zip plugin.json intro.mp4\n\n// after: host the asset externally and reference its URL\nzip -r pkg.zip plugin.json","handlingStrategy":"validation","validationCode":"func assertNoOversizedFile(path string) error {\n    r, err := zip.OpenReader(path)\n    if err != nil { return err }\n    defer r.Close()\n    for _, f := range r.File {\n        if f.UncompressedSize64 > 256<<20 {\n            return fmt.Errorf(\"entry %q declares %d bytes (>256MiB)\", f.Name, f.UncompressedSize64)\n        }\n    }\n    return nil\n}","typeGuard":null,"tryCatchPattern":"// ExtractLocalPackage already enforces this; map the returned error to a user-facing message\nif err != nil { return fmt.Errorf(\"package rejected: %w\", err) }","preventionTips":["Audit large assets with `unzip -lv` before packaging","Compress/downsample media so no single file exceeds 256 MiB uncompressed","Load very large runtime assets from a URL instead of bundling them"],"tags":["zip","archive","bazaar","limits","zip-bomb"],"backgroundTag":null,"analyzedSha":"251596fc0de2f9528c00c224252fd073a99973f4","analyzedAt":"2026-08-12T21:18:37.123Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}