This is an automated email from the ASF dual-hosted git repository.
gongchao pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/hertzbeat.git
The following commit(s) were added to refs/heads/master by this push:
new 07fd5b25c3 [improve] improve plugin upload validation (#4067)
07fd5b25c3 is described below
commit 07fd5b25c3dd27bc4def8a4c462c1a3d8b6d6b85
Author: Duansg <[email protected]>
AuthorDate: Tue Mar 17 09:14:38 2026 +0800
[improve] improve plugin upload validation (#4067)
---
.github/workflows/backend-build-test.yml | 1 +
.../manager/service/impl/PluginServiceImpl.java | 4 +++
.../manager/service/PluginServiceTest.java | 34 ++++++++++++++++++++++
3 files changed, 39 insertions(+)
diff --git a/.github/workflows/backend-build-test.yml
b/.github/workflows/backend-build-test.yml
index 34917e8e50..bac52c86cb 100644
--- a/.github/workflows/backend-build-test.yml
+++ b/.github/workflows/backend-build-test.yml
@@ -52,6 +52,7 @@ jobs:
uses: codecov/[email protected]
with:
token: ${{ secrets.CODECOV_TOKEN }}
+ fail_ci_if_error: false
verbose: true
- name: Build Image
diff --git
a/hertzbeat-manager/src/main/java/org/apache/hertzbeat/manager/service/impl/PluginServiceImpl.java
b/hertzbeat-manager/src/main/java/org/apache/hertzbeat/manager/service/impl/PluginServiceImpl.java
index 963275738c..a8206b35bf 100644
---
a/hertzbeat-manager/src/main/java/org/apache/hertzbeat/manager/service/impl/PluginServiceImpl.java
+++
b/hertzbeat-manager/src/main/java/org/apache/hertzbeat/manager/service/impl/PluginServiceImpl.java
@@ -490,6 +490,10 @@ public class PluginServiceImpl implements PluginService {
while (entries.hasMoreElements()) {
JarEntry entry = entries.nextElement();
File file = new File(libDir, entry.getName());
+ String canonicalLibDir = libDir.getCanonicalPath() +
File.separator;
+ if (!file.getCanonicalPath().startsWith(canonicalLibDir)) {
+ throw new IOException("Zip Slip detected: " +
entry.getName());
+ }
if (entry.isDirectory()) {
continue;
}
diff --git
a/hertzbeat-manager/src/test/java/org/apache/hertzbeat/manager/service/PluginServiceTest.java
b/hertzbeat-manager/src/test/java/org/apache/hertzbeat/manager/service/PluginServiceTest.java
index fef26765d3..5c3181c914 100644
---
a/hertzbeat-manager/src/test/java/org/apache/hertzbeat/manager/service/PluginServiceTest.java
+++
b/hertzbeat-manager/src/test/java/org/apache/hertzbeat/manager/service/PluginServiceTest.java
@@ -19,7 +19,9 @@ package org.apache.hertzbeat.manager.service;
import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertInstanceOf;
import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyList;
import static org.mockito.ArgumentMatchers.anyLong;
@@ -30,12 +32,18 @@ import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.lang.reflect.Method;
import java.nio.charset.StandardCharsets;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Optional;
import java.util.Set;
+import java.util.jar.JarEntry;
+import java.util.jar.JarOutputStream;
import org.apache.hertzbeat.common.constants.PluginType;
import org.apache.hertzbeat.common.entity.manager.PluginItem;
import org.apache.hertzbeat.common.entity.manager.PluginMetadata;
@@ -48,6 +56,7 @@ import
org.apache.hertzbeat.manager.service.impl.PluginServiceImpl;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
+import org.junit.jupiter.api.io.TempDir;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
@@ -159,4 +168,29 @@ class PluginServiceTest {
verify(metadataDao, times(1)).findAll(any(Specification.class),
any(PageRequest.class));
}
+ @Test
+ void testZipSlipDetected(@TempDir File tempDir) throws Exception {
+ File maliciousJar = new File(tempDir, "malicious.jar");
+ try (JarOutputStream jos = new JarOutputStream(new
FileOutputStream(maliciousJar))) {
+ JarEntry evilEntry = new JarEntry("../../evil.jar");
+ jos.putNextEntry(evilEntry);
+ jos.write("malicious-content".getBytes(StandardCharsets.UTF_8));
+ jos.closeEntry();
+ }
+ Method method = PluginServiceImpl.class.getDeclaredMethod(
+ "loadLibInPlugin", String.class, Long.class);
+ method.setAccessible(true);
+
+ Exception exception = assertThrows(Exception.class, () -> {
+ try {
+ method.invoke(pluginService, maliciousJar.getAbsolutePath(),
1L);
+ } catch (java.lang.reflect.InvocationTargetException e) {
+ throw e.getCause();
+ }
+ });
+
+ assertInstanceOf(IOException.class, exception);
+ assertTrue(exception.getMessage().contains("Zip Slip detected"));
+ }
+
}
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]