chinabugotech/hutool · critical · UtilException
Zip bomb attack detected, invalid sizes: compressed {}, unco
Error message
Zip bomb attack detected, invalid sizes: compressed {}, uncompressed {}, name {} What it means
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.
Source
Thrown at hutool-core/src/main/java/cn/hutool/core/compress/ZipReader.java:268
*
* @param entry {@link ZipEntry}
* @return 检查后的{@link ZipEntry}
*/
private ZipEntry checkZipBomb(ZipEntry entry) {
if (null == entry) {
return null;
}
if(maxSizeDiff < 0 || entry.isDirectory()){
// 目录不检查
return entry;
}
final long compressedSize = entry.getCompressedSize();
final long uncompressedSize = entry.getSize();
if (compressedSize < 0 || uncompressedSize < 0 ||
// 默认压缩比例是100倍,一旦发现压缩率超过这个阈值,被认为是Zip bomb
compressedSize * maxSizeDiff < uncompressedSize) {
throw new UtilException("Zip bomb attack detected, invalid sizes: compressed {}, uncompressed {}, name {}",
compressedSize, uncompressedSize, entry.getName());
}
return entry;
}
}
View on GitHub (pinned to 8870454b2a)
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.
Example fix
// before
ZipReader.of(uploadFile).readAll();
// after - raise threshold for media-heavy archives
ZipReader.of(uploadFile)
.setMaxSizeDiff(500)
.readAll(); Defensive patterns
Strategy: validation
Validate before calling
// before reading, scan entries and reject extreme ratios
try (ZipFile zf = new ZipFile(file)) {
final long MAX_RATIO = 100L;
Enumeration<? extends ZipEntry> en = zf.entries();
while (en.hasMoreElements()) {
ZipEntry e = en.nextElement();
if (!e.isDirectory() && e.getCompressedSize() > 0
&& e.getSize() > e.getCompressedSize() * MAX_RATIO) {
throw new IOException("Refused zip entry with extreme ratio: " + e.getName());
}
}
}
// safe to pass to ZipReader now (or raise setMaxSizeDiff accordingly) Try / catch
try {
ZipReader.of(file).readAll();
} catch (UtilException e) {
if (e.getMessage().contains("Zip bomb")) {
// quarantine the file, log, reject the upload
} else {
throw e;
}
} Prevention
- 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).
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- Paths or ins is empty !
- Paths length is not equals to ins length !
- Read limit exceeded
- Unauthorized deserialization attempt by black list
- Unauthorized deserialization attempt
AI-assisted analysis of chinabugotech/hutool@8870454b2a (2026-08-14).
Data as JSON: /api/errors/01fa93abe93957d4.
Report an issue: GitHub.