jeecgboot/JeecgBoot · error · IOException
解压文件数量超限,可能是zip bomb攻击
Error message
解压文件数量超限,可能是zip bomb攻击
What it means
Thrown by AiragKnowledgeDocServiceImpl.unzipFile() when the number of entries in the zip archive exceeds MAX_ENTRY_COUNT (10000). This is a zip-bomb defense — malicious archives can contain millions of entries to exhaust disk space or processing time. The counter increments for every entry including directories and skipped entries.
Source
Thrown at jeecg-boot/jeecg-boot-module/jeecg-boot-module-airag/src/main/java/org/jeecg/modules/airag/llm/service/impl/AiragKnowledgeDocServiceImpl.java:418
* @author chenrui
* @date 2025/4/28 17:02
*/
private static void unzipFile(Path zipFilePath, Path targetDir, Consumer<File> afterExtract) throws IOException {
long totalUnzippedSize = 0;
int entryCount = 0;
if (!Files.exists(targetDir)) {
Files.createDirectories(targetDir);
}
try (ZipFile zipFile = new ZipFile(zipFilePath.toFile())) {
Enumeration<ZipArchiveEntry> entries = zipFile.getEntries();
while (entries.hasMoreElements()) {
ZipArchiveEntry entry = entries.nextElement();
entryCount++;
if (entryCount > MAX_ENTRY_COUNT) {
throw new IOException("解压文件数量超限,可能是zip bomb攻击");
}
//update-begin---author:scott ---date:2026-04-16 for:【issues/9551】macOS压缩包隐藏文件过滤-----------
if (shouldSkipZipEntry(entry.getName())) {
log.info("跳过压缩包中的隐藏文件: {}", entry.getName());
continue;
}
//update-end---author:scott ---date:2026-04-16 for:【issues/9551】macOS压缩包隐藏文件过滤-----------
Path newPath = safeResolve(targetDir, entry.getName());
if (entry.isDirectory()) {
Files.createDirectories(newPath);
} else {
Files.createDirectories(newPath.getParent());
try (InputStream is = zipFile.getInputStream(entry);
OutputStream os = Files.newOutputStream(newPath)) {
View on GitHub (pinned to 96fb33f5ec)
Solutions
- Reduce the number of files in the zip archive by removing unnecessary files or splitting into multiple archives.
- If the limit is too low for legitimate use cases, increase MAX_ENTRY_COUNT (currently 10000) — but weigh the security implications.
- Exclude hidden files, metadata directories (.git, __MACOSX, node_modules) before zipping.
Defensive patterns
Strategy: validation
Validate before calling
// Pre-check zip entry count before full extraction
try (ZipFile zf = new ZipFile(zipFile.toFile())) {
int count = 0;
Enumeration<ZipArchiveEntry> e = zf.getEntries();
while (e.hasMoreElements()) { e.nextElement(); count++; }
if (count > 10000) {
throw new JeecgBootException("压缩包内文件数量超过10000个,请精简后重试");
}
} Try / catch
try {
unzipFile(zipFilePath, targetDir, callback);
} catch (IOException e) {
if (e.getMessage().contains("zip bomb")) {
log.warn("Zip bomb entry count detected: {}", e.getMessage());
throw new JeecgBootException("压缩包文件数量超限,请减少文件数量");
}
throw e;
} Prevention
- Exclude unnecessary files (node_modules, .git, __MACOSX) before creating the archive.
- Split large archives into smaller batches.
- Inform users of the 10000-entry limit in upload documentation.
When it happens
Trigger: Uploading a zip archive containing more than 10000 entries. Each ZipArchiveEntry increments the counter before any skip logic runs, so even entries that would be filtered (like macOS hidden files) count toward the limit.
Common situations: A legitimate archive with many small files (e.g. node_modules, source code repositories) exceeds 10000 entries; a malicious zip-bomb designed with excessive entries; a large dataset archive.
Related errors
AI-assisted analysis of jeecgboot/JeecgBoot@96fb33f5ec (2026-08-14).
Data as JSON: /api/errors/6e7d22d87bffa568.
Report an issue: GitHub.