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

  1. Reduce the number of files in the zip archive by removing unnecessary files or splitting into multiple archives.
  2. If the limit is too low for legitimate use cases, increase MAX_ENTRY_COUNT (currently 10000) — but weigh the security implications.
  3. 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

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.