This is an automated email from the ASF dual-hosted git repository.
Aias00 pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/shenyu.git
The following commit(s) were added to refs/heads/master by this push:
new 74644fbf1a fix: Add decompression size limits to
ZipUtil.unzip()[#6400] (#6416)
74644fbf1a is described below
commit 74644fbf1a5873810fd5e4377f7690ca8a520c76
Author: hengyuss <[email protected]>
AuthorDate: Mon Jul 6 15:38:56 2026 +0800
fix: Add decompression size limits to ZipUtil.unzip()[#6400] (#6416)
* fix: Add decompression size limits to ZipUtil.unzip()[#6400]
* fix: fix checkStyle
* fix: fix test
* fix: remove magic num in ConfigServiceTest.java
---------
Co-authored-by: aias00 <[email protected]>
---
.../admin/service/impl/ConfigsServiceImpl.java | 23 ++++++++++-
.../org/apache/shenyu/admin/utils/ZipUtil.java | 44 +++++++++++++++++++++-
shenyu-admin/src/main/resources/application.yml | 6 +++
.../shenyu/admin/service/ConfigsServiceTest.java | 10 +++++
4 files changed, 79 insertions(+), 4 deletions(-)
diff --git
a/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/impl/ConfigsServiceImpl.java
b/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/impl/ConfigsServiceImpl.java
index 99842dc26a..5e4e65c592 100644
---
a/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/impl/ConfigsServiceImpl.java
+++
b/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/impl/ConfigsServiceImpl.java
@@ -64,6 +64,7 @@ import org.apache.shenyu.common.utils.JsonUtils;
import org.apache.shenyu.common.utils.ListUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import java.util.Comparator;
@@ -79,6 +80,24 @@ public class ConfigsServiceImpl implements ConfigsService {
private static final Logger LOG =
LoggerFactory.getLogger(ConfigsServiceImpl.class);
+ /**
+ * The max entry size for unzip.
+ */
+ @Value("${shenyu.config.import.max-entry-size:104857600}")
+ private long maxEntrySize;
+
+ /**
+ * The max total size for unzip.
+ */
+ @Value("${shenyu.config.import.max-total-size:209715200}")
+ private long maxTotalSize;
+
+ /**
+ * The max entry count for unzip.
+ */
+ @Value("${shenyu.config.import.max-entry-count:1000}")
+ private int maxEntryCount;
+
/**
* The AppAuth service.
*/
@@ -342,7 +361,7 @@ public class ConfigsServiceImpl implements ConfigsService {
@Override
public ShenyuAdminResult configsImport(final byte[] source) {
- ZipUtil.UnZipResult unZipResult = ZipUtil.unzip(source);
+ ZipUtil.UnZipResult unZipResult = ZipUtil.unzip(source, maxEntrySize,
maxTotalSize, maxEntryCount);
List<ZipUtil.ZipItem> zipItemList = unZipResult.getZipItemList();
if (CollectionUtils.isEmpty(zipItemList)) {
LOG.info("import file is empty");
@@ -387,7 +406,7 @@ public class ConfigsServiceImpl implements ConfigsService {
@Override
public ShenyuAdminResult configsImport(final String namespace, final
byte[] source) {
- ZipUtil.UnZipResult unZipResult = ZipUtil.unzip(source);
+ ZipUtil.UnZipResult unZipResult = ZipUtil.unzip(source, maxEntrySize,
maxTotalSize, maxEntryCount);
List<ZipUtil.ZipItem> zipItemList = unZipResult.getZipItemList();
if (CollectionUtils.isEmpty(zipItemList)) {
LOG.info("import file is empty");
diff --git
a/shenyu-admin/src/main/java/org/apache/shenyu/admin/utils/ZipUtil.java
b/shenyu-admin/src/main/java/org/apache/shenyu/admin/utils/ZipUtil.java
index 5dda4bed3b..16f8cf7b54 100644
--- a/shenyu-admin/src/main/java/org/apache/shenyu/admin/utils/ZipUtil.java
+++ b/shenyu-admin/src/main/java/org/apache/shenyu/admin/utils/ZipUtil.java
@@ -38,10 +38,21 @@ public final class ZipUtil {
private static final Logger LOG = LoggerFactory.getLogger(ZipUtil.class);
+ /**
+ * 100 MB per entry.
+ */
+ private static final long MAX_ENTRY_SIZE = 100L * 1024 * 1024;
+
+ /**
+ * 200 MB total.
+ */
+ private static final long MAX_TOTAL_SIZE = 200L * 1024 * 1024;
+
+ private static final int MAX_ENTRY_COUNT = 1000;
+
private ZipUtil() {
}
-
/**
* zip method.
*
@@ -66,23 +77,52 @@ public final class ZipUtil {
}
/**
- * unzip method.
+ * unzip method with default size limits.
*
* @param source source
* @return unzip result
*/
public static UnZipResult unzip(final byte[] source) {
+ return unzip(source, MAX_ENTRY_SIZE, MAX_TOTAL_SIZE, MAX_ENTRY_COUNT);
+ }
+
+ /**
+ * unzip method with configurable size limits.
+ *
+ * @param source source
+ * @param maxEntrySize max entry size
+ * @param maxTotalSize max total size
+ * @param maxEntryCount max entry count
+ * @return unzip result
+ */
+ public static UnZipResult unzip(final byte[] source, final long
maxEntrySize,
+ final long maxTotalSize, final int
maxEntryCount) {
List<ZipItem> itemList = Lists.newArrayList();
+ long totalSize = 0L;
+ int entryCount = 0;
try (ZipInputStream zipIn = new ZipInputStream(new
ByteArrayInputStream(source))) {
ZipEntry entry;
while (Objects.nonNull(entry = zipIn.getNextEntry())) {
if (entry.isDirectory()) {
continue;
}
+ entryCount++;
+ if (entryCount > maxEntryCount) {
+ throw new IllegalArgumentException("entry count exceeds
maximum of " + maxEntryCount);
+ }
try (ByteArrayOutputStream out = new ByteArrayOutputStream()) {
byte[] buffer = new byte[1024];
int offset;
+ long entrySize = 0L;
while ((offset = zipIn.read(buffer)) != -1) {
+ entrySize += offset;
+ totalSize += offset;
+ if (entrySize > maxEntrySize) {
+ throw new IllegalArgumentException("entry size
exceeds maximum allowed value.");
+ }
+ if (totalSize > maxTotalSize) {
+ throw new IllegalArgumentException("total size
exceeds maximum allowed value.");
+ }
out.write(buffer, 0, offset);
}
String entryName = entry.getName();
diff --git a/shenyu-admin/src/main/resources/application.yml
b/shenyu-admin/src/main/resources/application.yml
index 0e986c0c0a..a0850d0bea 100755
--- a/shenyu-admin/src/main/resources/application.yml
+++ b/shenyu-admin/src/main/resources/application.yml
@@ -227,6 +227,11 @@ shenyu:
apiServer: "https://127.0.0.1:6443"
token: "token"
caCertPath: "/etc/kubernetes/pki/ca.crt"
+ config:
+ import:
+ max-entry-size: 104857600
+ max-total-size: 209715200
+ max-entry-count: 1000
springdoc:
api-docs:
@@ -246,3 +251,4 @@ logging:
org.apache.shenyu.lottery: info
org.apache.shenyu: info
# org.apache.shenyu.admin.utils.HttpUtils: debug
+
diff --git
a/shenyu-admin/src/test/java/org/apache/shenyu/admin/service/ConfigsServiceTest.java
b/shenyu-admin/src/test/java/org/apache/shenyu/admin/service/ConfigsServiceTest.java
index b8023af730..b113f75b31 100644
---
a/shenyu-admin/src/test/java/org/apache/shenyu/admin/service/ConfigsServiceTest.java
+++
b/shenyu-admin/src/test/java/org/apache/shenyu/admin/service/ConfigsServiceTest.java
@@ -29,6 +29,7 @@ import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
+import org.springframework.test.util.ReflectionTestUtils;
import java.util.Collections;
import java.util.List;
@@ -45,6 +46,12 @@ import static org.mockito.Mockito.when;
@ExtendWith(MockitoExtension.class)
public final class ConfigsServiceTest {
+ private static final long MAX_ENTRY_SIZE = 100L * 1024 * 1024;
+
+ private static final long MAX_TOTAL_SIZE = 200L * 1024 * 1024;
+
+ private static final int MAX_ENTRY_COUNT = 1000;
+
private ConfigsServiceImpl configsService;
@Mock
@@ -84,6 +91,9 @@ public final class ConfigsServiceTest {
public void setUp() {
configsService = new ConfigsServiceImpl(appAuthService, pluginService,
namespacePluginService, pluginHandleService, selectorService, ruleService,
metaDataService, shenyuDictService, proxySelectorService,
discoveryService, discoveryUpstreamService, Collections.emptyList());
+ ReflectionTestUtils.setField(configsService, "maxEntrySize",
MAX_ENTRY_SIZE);
+ ReflectionTestUtils.setField(configsService, "maxTotalSize",
MAX_TOTAL_SIZE);
+ ReflectionTestUtils.setField(configsService, "maxEntryCount",
MAX_ENTRY_COUNT);
}
@Test