[Git][java-team/axmlrpc][upstream] 4 commits: New upstream version 1.14.0
Emmanuel Bourg (@ebourg)
gitlab at salsa.debian.org
Thu Sep 24 13:40:11 BST 2026
Emmanuel Bourg pushed to branch upstream at Debian Java Maintainers / axmlrpc
Commits:
6ed4029d by Emmanuel Bourg at 2026-09-24T13:22:09+02:00
New upstream version 1.14.0
- - - - -
54375d70 by Emmanuel Bourg at 2026-09-24T13:48:02+02:00
New upstream version 1.15.0
- - - - -
20a79618 by Emmanuel Bourg at 2026-09-24T13:57:09+02:00
New upstream version 1.16.0
- - - - -
bb3c5398 by Emmanuel Bourg at 2026-09-24T14:02:40+02:00
New upstream version 1.17.0
- - - - -
9 changed files:
- Changelog
- README.md
- pom.xml
- src/main/java/de/timroes/axmlrpc/ResponseParser.java
- src/main/java/de/timroes/axmlrpc/XMLRPCClient.java
- src/main/java/de/timroes/axmlrpc/XMLRPCTimeoutException.java
- src/main/java/de/timroes/axmlrpc/XMLUtil.java
- src/main/java/de/timroes/axmlrpc/serializer/SerializerHandler.java
- src/test/java/de/timroes/axmlrpc/serializer/TestResponseParser.java
Changes:
=====================================
Changelog
=====================================
@@ -1,3 +1,16 @@
+Fix options added in 1.15.0 (those were not usable)
+
+1.15.0
+Add
+- setConnectTimeout
+- setReadTimeout
+- callWithOverridenTimeout
+
+1.14.0
+Fix security issue CWE-611
+Add support for CDATA section in the server response
+
+1.13.0
DateTime serializer format is now injectable
1.12.1
=====================================
README.md
=====================================
@@ -5,10 +5,6 @@ aXMLRPC is a Java library with a leightweight XML-RPC client. XML-RPC is
a specification for making remote procedure calls over the HTTP protocol
in an XML format. The specificationc can be found under http://www.xmlrpc.com/spec.
-The library was developed for the use with Android. Since it has no dependencies to
-any Android library or any other 3rd-party library, it is fully functional in any
-common java virtual machine (not only on Android).
-
You can control the client with some flags to extend its functionality. See the section
about flags.
=====================================
pom.xml
=====================================
@@ -3,7 +3,7 @@
<modelVersion>4.0.0</modelVersion>
<groupId>fr.turri</groupId>
<artifactId>aXMLRPC</artifactId>
- <version>1.13.0</version>
+ <version>1.17.0</version>
<packaging>jar</packaging>
<name>aXMLRPC</name>
<description>Lightweight Java XML-RPC working also on Android.</description>
@@ -42,10 +42,15 @@
<artifactId>jISO8601</artifactId>
<version>0.2</version>
</dependency>
+ <dependency>
+ <groupId>xerces</groupId>
+ <artifactId>xercesImpl</artifactId>
+ <version>2.12.2</version>
+ </dependency>
<dependency>
<groupId>com.github.tomakehurst</groupId>
<artifactId>wiremock-jre8</artifactId>
- <version>2.28.0</version>
+ <version>2.35.1</version>
<scope>test</scope>
</dependency>
</dependencies>
@@ -53,7 +58,7 @@
<connection>scm:git:https://github.com/gturri/aXMLRPC.git</connection>
<developerConnection>scm:git:git at github.com:gturri/aXMLRPC.git</developerConnection>
<url>https://github.com/gturri/aXMLRPC</url>
- <tag>aXMLRPC-1.13.0</tag>
+ <tag>aXMLRPC-1.17.0</tag>
</scm>
<build>
<pluginManagement>
=====================================
src/main/java/de/timroes/axmlrpc/ResponseParser.java
=====================================
@@ -10,6 +10,7 @@ import java.util.Map;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
@@ -45,9 +46,17 @@ public class ResponseParser {
public Object parse(SerializerHandler serializerHandler, InputStream response, boolean debugMode) throws XMLRPCException {
try {
-
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
+
+ // Ensure the xml parser won't allow exploitation of the vuln CWE-611
+ // (described on https://cwe.mitre.org/data/definitions/611.html )
+ factory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
+ factory.setExpandEntityReferences(false);
factory.setNamespaceAware(true);
+ factory.setXIncludeAware(false);
+ factory.setExpandEntityReferences(false);
+ // End of the configuration of the parser for CWE-611
+
DocumentBuilder builder = factory.newDocumentBuilder();
Document dom = builder.parse(response);
if (debugMode ){
=====================================
src/main/java/de/timroes/axmlrpc/XMLRPCClient.java
=====================================
@@ -196,7 +196,8 @@ public class XMLRPCClient {
private Proxy proxy;
- private int timeout;
+ private int connectTimeout;
+ private int readTimeout;
private final SerializerHandler serializerHandler;
/**
@@ -296,7 +297,7 @@ public class XMLRPCClient {
}
/**
- * Sets the time in seconds after which a call should timeout.
+ * Set both the connect timeout and the read timeout.
* If {@code timeout} will be zero or less the connection will never timeout.
* In case the connection times out an {@link XMLRPCTimeoutException} will
* be thrown for calls made by {@link #call(java.lang.String, java.lang.Object[])}.
@@ -307,7 +308,16 @@ public class XMLRPCClient {
* @param timeout The timeout for connections in seconds.
*/
public void setTimeout(int timeout) {
- this.timeout = timeout;
+ this.connectTimeout = timeout;
+ this.readTimeout = timeout;
+ }
+
+ public void setConnectTimeout(int timeout) {
+ this.connectTimeout = timeout;
+ }
+
+ public void setReadTimeout(int timeout) {
+ this.readTimeout = timeout;
}
/**
@@ -460,11 +470,31 @@ public class XMLRPCClient {
*
* @param method A method name to call.
* @param params An array of parameters for the method.
- * @return The result of the server.
+ * @return The result of the call.
* @throws XMLRPCException Will be thrown if an error occurred during the call.
*/
public Object call(String method, Object... params) throws XMLRPCException {
- return new Caller().call(method, params);
+ return callWithOverriddenTimeout(method, connectTimeout, readTimeout, params);
+ }
+
+ /**
+ * Call a remote procedure on the server. The method must be described by
+ * a method name. If the method requires parameters, this must be set.
+ * The type of the return object depends on the server. You should consult
+ * the server documentation and then cast the return value according to that.
+ * This method will block until the server returned a result (or an error occurred).
+ * Read the README file delivered with the source code of this library for more
+ * information.
+ *
+ * @param method A method name to call.
+ * @param connectTimeout The connect timeout to use for this call.
+ * @param readTimeout The read timeout to use for this call.
+ * @param params An array of parameters for the method.
+ * @return The result of the call.
+ * @throws XMLRPCException Will be thrown if an error occurred during the call.
+ */
+ public Object callWithOverriddenTimeout(String method, int connectTimeout, int readTimeout, Object[] params) throws XMLRPCException {
+ return new Caller().call(method, connectTimeout, readTimeout, params);
}
/**
@@ -483,8 +513,33 @@ public class XMLRPCClient {
* @return The id of the current request.
*/
public long callAsync(XMLRPCCallback listener, String methodName, Object... params) {
+ return callAsyncWithOverriddenTimeout(listener, methodName, connectTimeout, readTimeout, params);
+ }
+
+ /**
+ * Asynchronously call a remote procedure on the server. The method must be
+ * described by a method name. If the method requires parameters, this must
+ * be set. When the server returns a response the onResponse method is called
+ * on the listener. If the server returns an error the onServerError method
+ * is called on the listener. The onError method is called whenever something
+ * fails. This method returns immediately and returns an identifier for the
+ * request. All listener methods get this id as a parameter to distinguish
+ * between
+ * multiple requests.
+ *
+ * @param listener A listener, which will be notified about the server
+ * response or errors.
+ * @param methodName A method name to call on the server.
+ * @param connectTimeout The connect timeout to use for this call.
+ * @param readTimeout The read timeout to use for this call.
+ * @param params An array of parameters for the method.
+ * @return The id of the current request.
+ */
+ public long callAsyncWithOverriddenTimeout(
+ XMLRPCCallback listener, String methodName, int connectTimeout, int readTimeout,
+ Object... params) {
long id = System.currentTimeMillis();
- new Caller(listener, id, methodName, params).start();
+ new Caller(listener, id, methodName, connectTimeout, readTimeout, params).start();
return id;
}
@@ -549,6 +604,8 @@ public class XMLRPCClient {
private long threadId;
private String methodName;
private Object[] params;
+ private int connectTimeout;
+ private int readTimeout;
private volatile boolean canceled;
private HttpURLConnection http;
@@ -559,13 +616,18 @@ public class XMLRPCClient {
* @param listener The listener to notice about the response or an error.
* @param threadId An id that will be send to the listener.
* @param methodName The method name to call.
+ * @param connectTimeout The connect timeout to use for this call.
+ * @param readTimeout The read timeout to use for this call.
* @param params The parameters of the call or null.
*/
- public Caller(XMLRPCCallback listener, long threadId, String methodName, Object[] params) {
+ public Caller(XMLRPCCallback listener, long threadId, String methodName,
+ int connectTimeout, int readTimeout, Object[] params) {
this.listener = listener;
this.threadId = threadId;
this.methodName = methodName;
this.params = params;
+ this.connectTimeout = connectTimeout;
+ this.readTimeout = readTimeout;
}
/**
@@ -589,7 +651,7 @@ public class XMLRPCClient {
try {
backgroundCalls.put(threadId, this);
- Object o = this.call(methodName, params);
+ Object o = this.call(methodName, connectTimeout, readTimeout, params);
listener.onResponse(threadId, o);
} catch(CancelException ex) {
// Don't notify the listener, if the call has been canceled.
@@ -624,11 +686,12 @@ public class XMLRPCClient {
*
* @param methodName A method name to call.
* @param params An array of parameters for the method.
- * @return The result of the server.
+ * @param connectTimeout The connect timeout to use for this call.
+ * @param readTimeout The read timeout to use for this call.
+ * @return The result of the call.
* @throws XMLRPCException Will be thrown if an error occurred during the call.
*/
- public Object call(String methodName, Object[] params) throws XMLRPCException {
-
+ public Object call(String methodName, int connectTimeout, int readTimeout, Object[] params) throws XMLRPCException {
try {
Call c = createCall(methodName, params);
@@ -647,9 +710,11 @@ public class XMLRPCClient {
http.setDoInput(true);
// Set timeout
- if(timeout > 0) {
- http.setConnectTimeout(timeout * 1000);
- http.setReadTimeout(timeout * 1000);
+ if(connectTimeout > 0) {
+ http.setConnectTimeout(connectTimeout * 1000);
+ }
+ if (readTimeout > 0) {
+ http.setReadTimeout(readTimeout * 1000);
}
// Set the request parameters
@@ -715,7 +780,7 @@ public class XMLRPCClient {
URL oldURL = url;
url = new URL(newLocation);
http.disconnect();
- Object forwardedResult = call(methodName, params);
+ Object forwardedResult = call(methodName, connectTimeout, readTimeout, params);
// In case of temporary forward, restore original URL again for next call.
if(temporaryForward) {
@@ -747,7 +812,7 @@ public class XMLRPCClient {
return responseParser.parse(serializerHandler, istream, isFlagSet(FLAGS_DEBUG));
} catch(SocketTimeoutException ex) {
- throw new XMLRPCTimeoutException("The XMLRPC call timed out.");
+ throw new XMLRPCTimeoutException("The XMLRPC call timed out.", ex);
} catch (IOException ex) {
// If the thread has been canceled this exception will be thrown.
// So only throw an exception if the thread hasnt been canceled
=====================================
src/main/java/de/timroes/axmlrpc/XMLRPCTimeoutException.java
=====================================
@@ -7,9 +7,11 @@ package de.timroes.axmlrpc;
* @author Tim Roes
*/
public class XMLRPCTimeoutException extends XMLRPCException {
-
XMLRPCTimeoutException(String ex) {
super(ex);
}
+ XMLRPCTimeoutException(String message, Exception cause) {
+ super(message, cause);
+ }
}
=====================================
src/main/java/de/timroes/axmlrpc/XMLUtil.java
=====================================
@@ -76,7 +76,7 @@ public class XMLUtil {
continue;
}
- if(n.getNodeType() != Node.TEXT_NODE) {
+ if(n.getNodeType() != Node.TEXT_NODE && n.getNodeType() != Node.CDATA_SECTION_NODE) {
throw new XMLRPCException("Element must contain only text elements.");
}
=====================================
src/main/java/de/timroes/axmlrpc/serializer/SerializerHandler.java
=====================================
@@ -183,7 +183,7 @@ public class SerializerHandler {
byte[] old = (byte[])object;
Byte[] boxed = new Byte[old.length];
for(int i = 0; i < boxed.length; i++) {
- boxed[i] = new Byte(old[i]);
+ boxed[i] = Byte.valueOf(old[i]);
}
object = boxed;
s = base64;
=====================================
src/test/java/de/timroes/axmlrpc/serializer/TestResponseParser.java
=====================================
@@ -13,7 +13,7 @@ import org.junit.Rule;
import com.github.tomakehurst.wiremock.junit.WireMockRule;
-import de.timroes.axmlrpc.XMLRPCClient;
+import de.timroes.axmlrpc.*;
public class TestResponseParser {
private final int port = 8080;
@@ -72,14 +72,52 @@ public class TestResponseParser {
assertTrue("Should have thrown because date was empty and we used the default behavior", didThrow);
}
+ @Test
+ public void robustToCWE611() throws Exception {
+ setMockWithRawContent("<?xml version=\"1.0\"?> <!DOCTYPE replace [<!ENTITY ent SYSTEM \"http://localhost/malware\"> ]><methodResponse><params><param><value><string>&ent;</string></value></param></params></methodResponse>");
+ boolean didThrowExpectedException = false;
+
+ try {
+ makeDummyCall(XMLRPCClient.FLAGS_NONE);
+ } catch(XMLRPCException e) {
+ didThrowExpectedException = isCWE611ExceptedException(e);
+ if (!didThrowExpectedException) {
+ // if we don't get the exception we were expecting, rethrow so user has clues about what went wrong
+ // and can troubleshoot the test more easily
+ throw e;
+ }
+ }
+
+ assertTrue("Should have thrown because this payload is malicious", didThrowExpectedException);
+ }
+
+ @Test
+ public void canParseResponseWithCDATA() throws Exception {
+ setMockWithXmlRpcContent("<value><string><![CDATA[ab<&>cd]]></string></value>");
+
+ assertEquals("ab<&>cd", makeDummyCall());
+ }
+
private void setMockWithXmlRpcContent(String content){
+ setMockWithRawContent("<methodResponse><params><param>" + content + "</param></params></methodResponse>");
+ }
+
+ private void setMockWithRawContent(String rawContent) {
stubFor(post(urlEqualTo(endPoint))
.willReturn(aResponse()
.withStatus(200)
- .withBody("<methodResponse><params><param>" + content + "</param></params></methodResponse>")
+ .withBody(rawContent)
));
}
+ private boolean isCWE611ExceptedException(XMLRPCException e) {
+ Throwable cause = e.getCause();
+ if (cause == null) {
+ return false;
+ }
+ return cause.getMessage().contains("DOCTYPE is disallowed");
+ }
+
private Object makeDummyCall() throws Exception {
return makeDummyCall(XMLRPCClient.FLAGS_NONE);
}
View it on GitLab: https://salsa.debian.org/java-team/axmlrpc/-/compare/13ea0979f3cca92b14f06296a88954cf521aa102...bb3c539897d0b7b5748229c502a6b0affcba6090
--
View it on GitLab: https://salsa.debian.org/java-team/axmlrpc/-/compare/13ea0979f3cca92b14f06296a88954cf521aa102...bb3c539897d0b7b5748229c502a6b0affcba6090
You're receiving this email because of your account on salsa.debian.org. Manage all notifications: https://salsa.debian.org/-/profile/notifications | Help: https://salsa.debian.org/help
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://alioth-lists.debian.net/pipermail/pkg-java-commits/attachments/20260924/579bfdcf/attachment.htm>
More information about the pkg-java-commits
mailing list