{"record":{"id":"01fa93abe93957d4","repo":"chinabugotech/hutool","slug":"zip-bomb-attack-detected-invalid-sizes-compresse","errorCode":null,"errorMessage":"Zip bomb attack detected, invalid sizes: compressed {}, uncompressed {}, name {}","messagePattern":"Zip bomb attack detected, invalid sizes: compressed (.+?), uncompressed (.+?), name (.+?)","errorType":"exception","errorClass":"UtilException","httpStatus":null,"severity":"critical","filePath":"hutool-core/src/main/java/cn/hutool/core/compress/ZipReader.java","lineNumber":268,"sourceCode":"\t *\n\t * @param entry {@link ZipEntry}\n\t * @return 检查后的{@link ZipEntry}\n\t */\n\tprivate ZipEntry checkZipBomb(ZipEntry entry) {\n\t\tif (null == entry) {\n\t\t\treturn null;\n\t\t}\n\t\tif(maxSizeDiff < 0 || entry.isDirectory()){\n\t\t\t// 目录不检查\n\t\t\treturn entry;\n\t\t}\n\n\t\tfinal long compressedSize = entry.getCompressedSize();\n\t\tfinal long uncompressedSize = entry.getSize();\n\t\tif (compressedSize < 0 || uncompressedSize < 0 ||\n\t\t\t\t// 默认压缩比例是100倍，一旦发现压缩率超过这个阈值，被认为是Zip bomb\n\t\t\t\tcompressedSize * maxSizeDiff < uncompressedSize) {\n\t\t\tthrow new UtilException(\"Zip bomb attack detected, invalid sizes: compressed {}, uncompressed {}, name {}\",\n\t\t\t\t\tcompressedSize, uncompressedSize, entry.getName());\n\t\t}\n\t\treturn entry;\n\t}\n}\n","sourceCodeStart":250,"sourceCodeEnd":274,"githubUrl":"https://github.com/chinabugotech/hutool/blob/8870454b2a0c29cc6ffd31dcf5667c8ceb2fc442/hutool-core/src/main/java/cn/hutool/core/compress/ZipReader.java#L250-L274","documentation":"ZipReader.checkZipBomb throws UtilException when a ZIP entry's uncompressed size exceeds compressed size by more than maxSizeDiff (default 100x), or when either size is negative. It is a security guard against zip-bomb archives that decompress to enormous volumes and exhaust memory/disk.","triggerScenarios":"Calling ZipReader.of(file).read() / readNext() on an archive containing an entry where entry.getCompressedSize()*100 < entry.getSize(), or where the entry reports negative sizes. Only triggers when maxSizeDiff >= 0 and the entry is not a directory.","commonSituations":"Processing user-uploaded zip files; archives containing already-compressed payloads (zip-in-zip, JPEG/PDF media, encrypted zip) that legitimately exceed 100:1 ratio; malicious archives crafted to trigger the protection.","solutions":["If the high ratio is expected, raise the threshold: configure the reader with a larger maxSizeDiff (e.g. ZipReader.of(file).setMaxSizeDiff(1000)) before iterating.","If you do not want the guard, disable it by setting maxSizeDiff to a negative value (guard is skipped when maxSizeDiff < 0).","Validate the archive source / scan entries and reject entries with extreme ratios before delegating to ZipReader.","Wrap the read loop in a try/catch on UtilException to skip or quarantine offending entries."],"exampleFix":"// before\nZipReader.of(uploadFile).readAll();\n\n// after - raise threshold for media-heavy archives\nZipReader.of(uploadFile)\n    .setMaxSizeDiff(500)\n    .readAll();","handlingStrategy":"validation","validationCode":"// before reading, scan entries and reject extreme ratios\ntry (ZipFile zf = new ZipFile(file)) {\n    final long MAX_RATIO = 100L;\n    Enumeration<? extends ZipEntry> en = zf.entries();\n    while (en.hasMoreElements()) {\n        ZipEntry e = en.nextElement();\n        if (!e.isDirectory() && e.getCompressedSize() > 0\n                && e.getSize() > e.getCompressedSize() * MAX_RATIO) {\n            throw new IOException(\"Refused zip entry with extreme ratio: \" + e.getName());\n        }\n    }\n}\n// safe to pass to ZipReader now (or raise setMaxSizeDiff accordingly)","typeGuard":null,"tryCatchPattern":"try {\n    ZipReader.of(file).readAll();\n} catch (UtilException e) {\n    if (e.getMessage().contains(\"Zip bomb\")) {\n        // quarantine the file, log, reject the upload\n    } else {\n        throw e;\n    }\n}","preventionTips":["Treat any user-uploaded zip as untrusted; scan entry size ratios before decompression.","Document expected compression ratios for your domain and configure maxSizeDiff accordingly.","Prefer ZipReader.setMaxSizeDiff over disabling the guard (maxSizeDiff < 0)."],"tags":["security","zip","compression","denial-of-service"],"backgroundTag":null,"analyzedSha":"8870454b2a0c29cc6ffd31dcf5667c8ceb2fc442","analyzedAt":"2026-08-14T04:01:12.892Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}