This is an automated email from the ASF dual-hosted git repository.
tomsun28 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 3496ebf497 [fix] fixed the JMX service URL validation issue (#4146)
3496ebf497 is described below
commit 3496ebf497163768eddfe4cfc1174ca26c2916d3
Author: Duansg <[email protected]>
AuthorDate: Thu May 28 09:39:54 2026 +0800
[fix] fixed the JMX service URL validation issue (#4146)
---
.../collector/collect/jmx/JmxCollectImpl.java | 31 +++++++++++++++-------
.../collector/collect/jmx/JmxCollectImplTest.java | 23 +++++++++++++++-
2 files changed, 44 insertions(+), 10 deletions(-)
diff --git
a/hertzbeat-collector/hertzbeat-collector-basic/src/main/java/org/apache/hertzbeat/collector/collect/jmx/JmxCollectImpl.java
b/hertzbeat-collector/hertzbeat-collector-basic/src/main/java/org/apache/hertzbeat/collector/collect/jmx/JmxCollectImpl.java
index 2995469877..1266cac69d 100644
---
a/hertzbeat-collector/hertzbeat-collector-basic/src/main/java/org/apache/hertzbeat/collector/collect/jmx/JmxCollectImpl.java
+++
b/hertzbeat-collector/hertzbeat-collector-basic/src/main/java/org/apache/hertzbeat/collector/collect/jmx/JmxCollectImpl.java
@@ -18,9 +18,11 @@
package org.apache.hertzbeat.collector.collect.jmx;
import java.io.IOException;
+import java.net.MalformedURLException;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
+import java.util.Locale;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
@@ -106,31 +108,42 @@ public class JmxCollectImpl extends AbstractCollect {
}
/**
- * Validate JMX URL
- *
+ * Validate JMX URL
+ *
* @param url JMX URL to validate
* @throws IllegalArgumentException if URL is potentially malicious
*/
private void validateJmxUrl(String url) throws IllegalArgumentException {
- // Only allow service:jmx:rmi protocol
- Assert.isTrue(url.startsWith("service:jmx:rmi:"), "Only
service:jmx:rmi protocol is supported");
+ JMXServiceURL serviceUrl;
+ try {
+ serviceUrl = new JMXServiceURL(url);
+ } catch (MalformedURLException e) {
+ throw new IllegalArgumentException("Invalid JMX URL", e);
+ }
+ Assert.isTrue("rmi".equalsIgnoreCase(serviceUrl.getProtocol()), "Only
service:jmx:rmi protocol is supported");
- String[] disallowedPatterns = { "ldap:", "rmi:", "iiop:", "nis:",
"dns:", "corbaname:", "http:", "https:" };
+ String lowerUrl = url.toLowerCase(Locale.ROOT);
+ String[] disallowedPatterns = {"ldap:", "iiop:", "nis:", "dns:",
"corbaname:", "http:", "https:"};
for (String pattern : disallowedPatterns) {
- if (url.contains(pattern) && !pattern.equals("rmi:///jndi/rmi:")) {
+ if (lowerUrl.contains(pattern)) {
throw new IllegalArgumentException("Potentially unsafe JNDI
protocol detected in URL: " + pattern);
}
}
+ String lowerPath = serviceUrl.getURLPath().toLowerCase(Locale.ROOT);
+ if (lowerPath.startsWith("/jndi/") &&
!lowerPath.startsWith("/jndi/rmi://")) {
+ throw new IllegalArgumentException("Only rmi JNDI protocol is
supported");
+ }
+
// Check for suspicious patterns
- if (url.contains("${") || url.contains("$[") || url.contains(":#") ||
url.contains(":/")) {
+ if (url.contains("${") || url.contains("$[") || url.contains(":#")) {
throw new IllegalArgumentException("Potentially malicious pattern
detected in JMX URL");
}
}
/**
- * Validate hostname format
- *
+ * Validate hostname format
+ *
* @param hostname Hostname to validate
* @return true if hostname is valid
*/
diff --git
a/hertzbeat-collector/hertzbeat-collector-basic/src/test/java/org/apache/hertzbeat/collector/collect/jmx/JmxCollectImplTest.java
b/hertzbeat-collector/hertzbeat-collector-basic/src/test/java/org/apache/hertzbeat/collector/collect/jmx/JmxCollectImplTest.java
index 152ba296d4..539d600ab6 100644
---
a/hertzbeat-collector/hertzbeat-collector-basic/src/test/java/org/apache/hertzbeat/collector/collect/jmx/JmxCollectImplTest.java
+++
b/hertzbeat-collector/hertzbeat-collector-basic/src/test/java/org/apache/hertzbeat/collector/collect/jmx/JmxCollectImplTest.java
@@ -50,7 +50,7 @@ class JmxCollectImplTest {
JmxProtocol jmx = JmxProtocol.builder().build();
jmx.setUrl("/stub/");
Metrics metrics = Metrics.builder().jmx(jmx).build();
-
+
jmxCollect.preCheck(metrics);
});
}
@@ -68,4 +68,25 @@ class JmxCollectImplTest {
void supportProtocol() {
assert
DispatchConstants.PROTOCOL_JMX.equals(jmxCollect.supportProtocol());
}
+
+ @Test
+ void preCheckShouldAcceptSupportedJmxRmiUrl() {
+ JmxProtocol jmx = JmxProtocol.builder()
+ .url("service:jmx:rmi:///jndi/rmi://127.0.0.1:9999/jmxrmi")
+ .build();
+ Metrics metrics = Metrics.builder().jmx(jmx).build();
+
+ assertDoesNotThrow(() -> jmxCollect.preCheck(metrics));
+ }
+
+ @Test
+ void preCheckShouldRejectUnsafeJndiProtocolInJmxRmiUrl() {
+ JmxProtocol jmx = JmxProtocol.builder()
+ .url("service:jmx:rmi:///jndi/ldap://127.0.0.1:1389/jmxrmi")
+ .build();
+ Metrics metrics = Metrics.builder().jmx(jmx).build();
+
+ assertThrows(IllegalArgumentException.class, () ->
jmxCollect.preCheck(metrics));
+ }
+
}
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]