{"record":{"id":"f67eb345f7831281","repo":"paperclipai/paperclip","slug":"unsupported-zip-archive-decompressed-contents-exc","errorCode":null,"errorMessage":"Unsupported zip archive: decompressed contents exceed the ${maxTotalDecompressedBytes}-byte limit.","messagePattern":"Unsupported zip archive: decompressed contents exceed the (.+?)-byte limit\\.","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/shared/src/portability-zip.ts","lineNumber":265,"sourceCode":"      throw new Error(\"Unsupported zip archive: data descriptors are not supported.\");\n    }\n\n    const nameOffset = offset + 30;\n    const bodyOffset = nameOffset + fileNameLength + extraFieldLength;\n    const bodyEnd = bodyOffset + compressedSize;\n    if (bodyEnd > bytes.length) {\n      throw new Error(\"Invalid zip archive: truncated file contents.\");\n    }\n\n    localHeaderCount += 1;\n    const rawArchivePath = textDecoder.decode(bytes.slice(nameOffset, nameOffset + fileNameLength));\n    const archivePath = normalizeArchivePath(rawArchivePath);\n    const isDirectoryEntry = /\\/$/.test(rawArchivePath.replace(/\\\\/g, \"/\"));\n    if (archivePath && !isDirectoryEntry) {\n      const entryBytes = inflateZipEntry(compressionMethod, bytes.slice(bodyOffset, bodyEnd), maxEntryDecompressedBytes);\n      totalDecompressedBytes += entryBytes.length;\n      if (totalDecompressedBytes > maxTotalDecompressedBytes) {\n        throw new Error(\n          `Unsupported zip archive: decompressed contents exceed the ${maxTotalDecompressedBytes}-byte limit.`,\n        );\n      }\n      entries.push({\n        path: archivePath,\n        body: bytesToPortableFileEntry(archivePath, entryBytes),\n      });\n    }\n\n    offset = bodyEnd;\n  }\n\n  // A complete archive always ends with a central directory after its local\n  // entries. If the scan ran off the end of the buffer without reaching one, the\n  // upload was truncated at a record boundary — fail closed rather than import a\n  // leading fragment. Then fully validate the central directory the EOCD points\n  // at so a truncated tail with a forged EOCD (whose count happens to match the\n  // surviving entries) cannot smuggle in a partial import.","sourceCodeStart":247,"sourceCodeEnd":283,"githubUrl":"https://github.com/paperclipai/paperclip/blob/120ae5428fa29bee300bcf806491cd4d965fbb7c/packages/shared/src/portability-zip.ts#L247-L283","documentation":"Decompression-bomb guard inside readZipArchive: an entry's decompressed output pushes the running total past the configured maxTotalDecompressedBytes cap. Fires when a zip (malicious or accidental) expands beyond the import budget, protecting memory before the whole archive is materialized.","triggerScenarios":"Thrown at packages/shared/src/portability-zip.ts:265 when the library encounters an invalid state.","commonSituations":"See trigger scenarios.","solutions":["Reduce total decompressed size under the limit, or extract in smaller archives."],"exampleFix":null,"handlingStrategy":"validation","validationCode":null,"typeGuard":null,"tryCatchPattern":null,"preventionTips":[],"tags":[],"backgroundTag":null,"analyzedSha":"120ae5428fa29bee300bcf806491cd4d965fbb7c","analyzedAt":"2026-08-18T22:49:45.177Z","contentChangedAt":"2026-08-18T22:49:45.177Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}