{"record":{"id":"7e6b1496ab293630","repo":"iOfficeAI/OfficeCLI","slug":"decompression-bomb","errorCode":"decompression_bomb","errorMessage":"Cannot open {Path.GetFileName(filePath)}: package has {archive.Entries.Count} entries (limit {DocumentLimits.MaxZipEntries}); rejected as a potential decompression bomb.","messagePattern":"Cannot open (.+?): package has (.+?) entries \\(limit (.+?)\\); rejected as a potential decompression bomb\\.","errorType":"exception","errorClass":"CliException","httpStatus":null,"severity":"error","filePath":"src/officecli/Handlers/DocumentHandlerFactory.cs","lineNumber":182,"sourceCode":"    /// corrupt_file error for it.\n    /// </summary>\n    private static void GuardDecompressionBomb(string filePath)\n    {\n        ZipArchive archive;\n        try\n        {\n            archive = ZipFile.OpenRead(filePath);\n        }\n        catch (InvalidDataException)\n        {\n            // Not a valid zip container — let OpenHandler surface corrupt_file.\n            return;\n        }\n\n        using (archive)\n        {\n            if (archive.Entries.Count > DocumentLimits.MaxZipEntries)\n                throw new CliException(\n                    $\"Cannot open {Path.GetFileName(filePath)}: package has {archive.Entries.Count} entries \" +\n                    $\"(limit {DocumentLimits.MaxZipEntries}); rejected as a potential decompression bomb.\")\n                {\n                    Code = \"decompression_bomb\",\n                    Suggestion = \"Verify the file is a genuine .docx/.xlsx/.pptx and not a crafted archive.\"\n                };\n\n            long totalUncompressed = 0;\n            long totalCompressed = 0;\n            foreach (var entry in archive.Entries)\n            {\n                totalUncompressed += entry.Length;\n                totalCompressed += entry.CompressedLength;\n\n                if (totalUncompressed > DocumentLimits.MaxUncompressedBytes)\n                    throw new CliException(\n                        $\"Cannot open {Path.GetFileName(filePath)}: uncompressed size exceeds \" +\n                        $\"{DocumentLimits.MaxUncompressedBytes / (1024 * 1024 * 1024)} GiB; \" +","sourceCodeStart":164,"sourceCodeEnd":200,"githubUrl":"https://github.com/iOfficeAI/OfficeCLI/blob/1ced45e900782c5083ed550ddf328ee974e425e7/src/officecli/Handlers/DocumentHandlerFactory.cs#L164-L200","documentation":"Thrown by the decompression-bomb guard (GuardDecompressionBomb) when the OOXML zip package contains more than DocumentLimits.MaxZipEntries (100,000) entries. This pre-scan uses ZipFile.OpenRead to read only the central directory — no entry is inflated — so it is cheap and catches crafted archives with millions of tiny entries designed to exhaust memory or processing time before the Open XML SDK touches them.","triggerScenarios":"A .docx/.xlsx/.pptx file whose zip central directory lists more than 100,000 entries. Legitimate Office documents rarely exceed a few hundred entries (one per XML part plus embedded media), so this threshold is far above any real document. A crafted file could stuff millions of zero-byte entries to exhaust zip-enumeration time or memory.","commonSituations":"A malicious or adversarial file crafted specifically to attack zip-processing tools; extremely rarely, a legitimate workbook with an enormous number of embedded objects (images, OLE parts) — but even then, hitting 100,000 entries would be extraordinary.","solutions":["Verify the file is genuine: 'unzip -l <file>' to list entries and confirm the count.","If the file is legitimate but unusually large, review whether the entry count is real or the file is corrupt.","Do not raise the limit — it exists for DoS protection. If you have a genuine use case, file a bug report with the document details."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// Pre-check zip entry count before opening\nusing var archive = System.IO.Compression.ZipFile.OpenRead(filePath);\nif (archive.Entries.Count > 100_000)\n    throw new InvalidOperationException($\"Suspicious entry count: {archive.Entries.Count}\");","typeGuard":null,"tryCatchPattern":"try\n{\n    var handler = DocumentHandlerFactory.Open(filePath);\n}\ncatch (CliException ex) when (ex.Code == \"decompression_bomb\" && ex.Message.Contains(\"entries\"))\n{\n    // The zip has too many entries — likely adversarial\n    logger.LogError(\"Rejected file with {Count} zip entries (limit 100000).\", ex.Message);\n    throw;\n}","preventionTips":["Do not process untrusted Office files without the built-in guards — they exist for DoS protection.","If accepting file uploads, scan with an antivirus and validate OOXML structure before processing.","Inspect suspicious files with 'unzip -l' to understand their structure.","Do not attempt to raise the MaxZipEntries limit — use a different processing strategy for genuinely huge files."],"tags":["dos-hardening","decompression-bomb","zip-entries","security-guard"],"backgroundTag":null,"analyzedSha":"1ced45e900782c5083ed550ddf328ee974e425e7","analyzedAt":"2026-08-13T13:01:07.193Z","schemaVersion":2},"datasetVersion":"2026-08-13T14:17:21.547Z"}