You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tika.apache.org by ta...@apache.org on 2026/10/21 12:29:23 UTC

(tika) branch main updated: TIKA-4985: raise the default zip-bomb ratio from 100 to 1000 (#3378)

This is an automated email from the ASF dual-hosted git repository.

tballison pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/tika.git


The following commit(s) were added to refs/heads/main by this push:
     new 9761e6d4b7 TIKA-4985: raise the default zip-bomb ratio from 100 to 1000 (#3378)
9761e6d4b7 is described below

commit 9761e6d4b744d5c951997b10adb074fe39d4d8d0
Author: Tim Allison <ta...@apache.org>
AuthorDate: Wed Oct 21 08:29:17 2026 -0400

    TIKA-4985: raise the default zip-bomb ratio from 100 to 1000 (#3378)
    
    The ratio is measured across the embedded tree against the container's bytes,
      so nested compression still trips it; at 100, ordinary compressed logs did.
    
      Co-Authored-By: Claude Opus 5.5 <no...@anthropic.com>
---
 CHANGES.txt                                                         | 5 +++++
 docs/modules/ROOT/pages/advanced/setting-limits.adoc                | 6 ++++--
 tika-core/src/main/java/org/apache/tika/config/OutputLimits.java    | 6 +++---
 .../src/main/java/org/apache/tika/sax/SecureContentHandler.java     | 2 +-
 .../src/test/java/org/apache/tika/sax/SecureContentHandlerTest.java | 4 ++--
 .../java/org/apache/tika/parser/RecursiveParserWrapperTest.java     | 6 +++++-
 .../src/test/java/org/apache/tika/config/OutputLimitsTest.java      | 2 +-
 7 files changed, 21 insertions(+), 10 deletions(-)

diff --git a/CHANGES.txt b/CHANGES.txt
index 72764c0a40..e1cf7c452d 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -247,6 +247,11 @@ Release 4.2.0 - unreleased
 
   SECURITY
 
+   * The default zip-bomb ratio (output-limits.zipBombRatio) is 1000, up from 100. The
+     ratio is measured across the whole embedded tree against the container's bytes, so
+     nested compression is still caught; at 100, ordinary compressed logs and text
+     tripped it. Set zipBombRatio to 100 to restore the old limit (TIKA-4985).
+
    * The Gemini VLM parser sends its API key in x-goog-api-key instead of the URL,
      which error messages and logs quote (TIKA-4985).
 
diff --git a/docs/modules/ROOT/pages/advanced/setting-limits.adoc b/docs/modules/ROOT/pages/advanced/setting-limits.adoc
index a3953a744c..7fd97d5e1a 100644
--- a/docs/modules/ROOT/pages/advanced/setting-limits.adoc
+++ b/docs/modules/ROOT/pages/advanced/setting-limits.adoc
@@ -75,7 +75,7 @@ these but `exception-reporting`, which has its own test:
       "throwOnWriteLimit": false,
       "maxXmlDepth": 100,
       "zipBombThreshold": 1000000,
-      "zipBombRatio": 100
+      "zipBombRatio": 1000
     },
     "timeout-limits": {
       "totalTaskTimeoutMillis": 3600000,
@@ -215,8 +215,10 @@ content is inlined into its container's XHTML.
 |Extracted characters before the zip-bomb ratio check activates.
 
 |`zipBombRatio`
-|100
+|1,000
 |Maximum ratio of extracted characters to input bytes read before flagging a zip bomb.
+Measured against the container's bytes across the whole embedded tree, so nested
+compression multiplies; one deflate layer alone stays under about 1,032.
 |===
 
 == Timeout limits
diff --git a/tika-core/src/main/java/org/apache/tika/config/OutputLimits.java b/tika-core/src/main/java/org/apache/tika/config/OutputLimits.java
index a2a1e6c4a5..c45f261968 100644
--- a/tika-core/src/main/java/org/apache/tika/config/OutputLimits.java
+++ b/tika-core/src/main/java/org/apache/tika/config/OutputLimits.java
@@ -33,7 +33,7 @@ import org.apache.tika.parser.ParseContext;
  *   <li>{@code maxXmlDepth} - maximum XML element nesting depth (default: 100)</li>
  *   <li>{@code maxPackageEntryDepth} - deprecated; use {@link EmbeddedLimits#setMaxDepth(int)}</li>
  *   <li>{@code zipBombThreshold} - characters before zip bomb check activates (default: 1,000,000)</li>
- *   <li>{@code zipBombRatio} - maximum output:input ratio for zip bomb detection (default: 100)</li>
+ *   <li>{@code zipBombRatio} - maximum output:input ratio for zip bomb detection (default: 1,000)</li>
  * </ul>
  * <p>
  * <b>writeLimit behavior:</b> The writeLimit is the TOTAL characters across all documents
@@ -55,7 +55,7 @@ import org.apache.tika.parser.ParseContext;
  *       "throwOnWriteLimit": false,
  *       "maxXmlDepth": 100,
  * *       "zipBombThreshold": 1000000,
- *       "zipBombRatio": 100
+ *       "zipBombRatio": 1000
  *     }
  *   }
  * }
@@ -80,7 +80,7 @@ public class OutputLimits implements Serializable {
     private int maxXmlDepth = 100;
     private int maxPackageEntryDepth = 20;
     private long zipBombThreshold = 1_000_000;
-    private long zipBombRatio = 100;
+    private long zipBombRatio = 1000;
 
     /**
      * No-arg constructor for Jackson deserialization.
diff --git a/tika-core/src/main/java/org/apache/tika/sax/SecureContentHandler.java b/tika-core/src/main/java/org/apache/tika/sax/SecureContentHandler.java
index c0189868c6..70101002ac 100644
--- a/tika-core/src/main/java/org/apache/tika/sax/SecureContentHandler.java
+++ b/tika-core/src/main/java/org/apache/tika/sax/SecureContentHandler.java
@@ -66,7 +66,7 @@ public class SecureContentHandler extends ContentHandlerDecorator {
     /**
      * Maximum compression ratio.
      */
-    private long ratio = 100;
+    private long ratio = 1000;
 
     /**
      * Maximum XML element nesting level.
diff --git a/tika-core/src/test/java/org/apache/tika/sax/SecureContentHandlerTest.java b/tika-core/src/test/java/org/apache/tika/sax/SecureContentHandlerTest.java
index 32ac2c6e94..f62dfa37df 100644
--- a/tika-core/src/test/java/org/apache/tika/sax/SecureContentHandlerTest.java
+++ b/tika-core/src/test/java/org/apache/tika/sax/SecureContentHandlerTest.java
@@ -100,7 +100,7 @@ public class SecureContentHandlerTest {
     @Test
     public void testManyCharactersPerByte() throws IOException {
         try {
-            char[] ch = new char[1000];
+            char[] ch = new char[2000];
             for (int i = 0; i < MANY_BYTES; i++) {
                 stream.read();
                 handler.characters(ch, 0, ch.length);
@@ -125,7 +125,7 @@ public class SecureContentHandlerTest {
                 new TemporaryResources(), metadata)) {
             SecureContentHandler lyingHandler =
                     new SecureContentHandler(new DefaultHandler(), lying);
-            char[] ch = new char[1000];
+            char[] ch = new char[2000];
             for (int i = 0; i < MANY_BYTES; i++) {
                 lying.read();
                 lyingHandler.characters(ch, 0, ch.length);
diff --git a/tika-parsers/tika-parsers-standard/tika-parsers-standard-integration-tests/src/test/java/org/apache/tika/parser/RecursiveParserWrapperTest.java b/tika-parsers/tika-parsers-standard/tika-parsers-standard-integration-tests/src/test/java/org/apache/tika/parser/RecursiveParserWrapperTest.java
index 33f1ba5a16..5530445b2b 100644
--- a/tika-parsers/tika-parsers-standard/tika-parsers-standard-integration-tests/src/test/java/org/apache/tika/parser/RecursiveParserWrapperTest.java
+++ b/tika-parsers/tika-parsers-standard/tika-parsers-standard-integration-tests/src/test/java/org/apache/tika/parser/RecursiveParserWrapperTest.java
@@ -41,6 +41,7 @@ import org.junit.jupiter.api.Test;
 import org.apache.tika.TikaLoaderHelper;
 import org.apache.tika.TikaTest;
 import org.apache.tika.config.EmbeddedLimits;
+import org.apache.tika.config.OutputLimits;
 import org.apache.tika.config.loader.TikaLoader;
 import org.apache.tika.exception.TikaException;
 import org.apache.tika.io.TikaInputStream;
@@ -495,9 +496,12 @@ public class RecursiveParserWrapperTest extends TikaTest {
         RecursiveParserWrapper wrapper = new RecursiveParserWrapper(AUTO_DETECT_PARSER);
         RecursiveParserWrapperHandler handler = new RecursiveParserWrapperHandler(
                 new BasicContentHandlerFactory(BasicContentHandlerFactory.HANDLER_TYPE.TEXT, -1));
+        // one deflate layer stays under the default ratio; the check across the tree is what's under test
+        ParseContext context = new ParseContext();
+        context.set(OutputLimits.class, new OutputLimits(-1, false, 100, 1_000_000, 100));
         try (TikaInputStream tis = TikaInputStream.get(bos.toByteArray())) {
             TikaException e = assertThrows(TikaException.class,
-                    () -> wrapper.parse(tis, handler, new Metadata(), new ParseContext()));
+                    () -> wrapper.parse(tis, handler, new Metadata(), context));
             assertTrue(e.getMessage().contains("Zip bomb"));
         }
     }
diff --git a/tika-serialization/src/test/java/org/apache/tika/config/OutputLimitsTest.java b/tika-serialization/src/test/java/org/apache/tika/config/OutputLimitsTest.java
index 7a663e97fc..6345d196a0 100644
--- a/tika-serialization/src/test/java/org/apache/tika/config/OutputLimitsTest.java
+++ b/tika-serialization/src/test/java/org/apache/tika/config/OutputLimitsTest.java
@@ -67,7 +67,7 @@ public class OutputLimitsTest extends TikaTest {
         assertEquals(100, limits.getMaxXmlDepth());
         assertEquals(20, limits.getMaxPackageEntryDepth());
         assertEquals(1_000_000, limits.getZipBombThreshold());
-        assertEquals(100, limits.getZipBombRatio());
+        assertEquals(1000, limits.getZipBombRatio());
     }
 
     @Test