This is an automated email from the ASF dual-hosted git repository.
coheigea pushed a commit to branch 4.1.x-fixes
in repository https://gitbox.apache.org/repos/asf/cxf.git
The following commit(s) were added to refs/heads/4.1.x-fixes by this push:
new 59bd119d4a0 Switch XML Security CryptoLoader to use URIResolver (#3280)
59bd119d4a0 is described below
commit 59bd119d4a0a8cbc4dabbeb4b46ba1bd5022b268
Author: Colm O hEigeartaigh <[email protected]>
AuthorDate: Tue Jul 7 10:03:16 2026 +0100
Switch XML Security CryptoLoader to use URIResolver (#3280)
(cherry picked from commit f7275f82309eb6b763152fb77f1afae7dc512f5d)
---
.../java/org/apache/cxf/resource/URIResolver.java | 5 +-
.../cxf/rs/security/common/CryptoLoader.java | 8 ++-
.../cxf/rs/security/common/CryptoLoaderTest.java | 78 ++++++++++++++++++++++
3 files changed, 87 insertions(+), 4 deletions(-)
diff --git a/core/src/main/java/org/apache/cxf/resource/URIResolver.java
b/core/src/main/java/org/apache/cxf/resource/URIResolver.java
index 1a823839b7d..633cf682e96 100644
--- a/core/src/main/java/org/apache/cxf/resource/URIResolver.java
+++ b/core/src/main/java/org/apache/cxf/resource/URIResolver.java
@@ -450,7 +450,10 @@ public class URIResolver implements AutoCloseable {
}
}
- private static void checkAllowedScheme(URL targetUrl) throws IOException {
+ /**
+ * Verifies that the URL scheme is permitted by URIResolver allowlist
policy.
+ */
+ public static void checkAllowedScheme(URL targetUrl) throws IOException {
String scheme = targetUrl.getProtocol();
if (scheme == null) {
return;
diff --git
a/rt/rs/security/xml/src/main/java/org/apache/cxf/rs/security/common/CryptoLoader.java
b/rt/rs/security/xml/src/main/java/org/apache/cxf/rs/security/common/CryptoLoader.java
index 6640156f1e5..4e4daa527b5 100644
---
a/rt/rs/security/xml/src/main/java/org/apache/cxf/rs/security/common/CryptoLoader.java
+++
b/rt/rs/security/xml/src/main/java/org/apache/cxf/rs/security/common/CryptoLoader.java
@@ -29,6 +29,7 @@ import java.util.concurrent.ConcurrentHashMap;
import org.apache.cxf.endpoint.Endpoint;
import org.apache.cxf.helpers.CastUtils;
import org.apache.cxf.message.Message;
+import org.apache.cxf.resource.URIResolver;
import org.apache.cxf.service.model.EndpointInfo;
import org.apache.wss4j.common.crypto.Crypto;
import org.apache.wss4j.common.crypto.CryptoFactory;
@@ -85,10 +86,11 @@ public class CryptoLoader {
}
public static Crypto loadCryptoFromURL(URL url) throws IOException,
WSSecurityException {
+ URIResolver.checkAllowedScheme(url);
Properties props = new Properties();
- InputStream in = url.openStream();
- props.load(in);
- in.close();
+ try (InputStream in = url.openStream()) {
+ props.load(in);
+ }
return CryptoFactory.getInstance(props);
}
diff --git
a/rt/rs/security/xml/src/test/java/org/apache/cxf/rs/security/common/CryptoLoaderTest.java
b/rt/rs/security/xml/src/test/java/org/apache/cxf/rs/security/common/CryptoLoaderTest.java
new file mode 100644
index 00000000000..f8cea46635f
--- /dev/null
+++
b/rt/rs/security/xml/src/test/java/org/apache/cxf/rs/security/common/CryptoLoaderTest.java
@@ -0,0 +1,78 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.cxf.rs.security.common;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.net.URL;
+import java.nio.charset.StandardCharsets;
+
+import org.apache.wss4j.common.crypto.Crypto;
+import org.apache.wss4j.common.ext.WSSecurityException;
+
+import org.junit.Test;
+
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+public class CryptoLoaderTest {
+
+ @Test
+ public void testDisallowedSchemeRejected() throws Exception {
+ URL url = new URL("ftp://example.com/crypto.properties");
+
+ try {
+ CryptoLoader.loadCryptoFromURL(url);
+ fail("Expected IOException for disallowed scheme");
+ } catch (IOException ex) {
+ assertTrue(ex.getMessage().contains("not permitted for
URIResolver"));
+ }
+ }
+
+ @Test
+ public void testAllowedFileSchemeLoadsCrypto() throws Exception {
+ File tmp = File.createTempFile("cxf-crypto", ".properties");
+ tmp.deleteOnExit();
+
+ String props =
"org.apache.wss4j.crypto.provider=org.apache.wss4j.common.crypto.Merlin\n"
+ + "org.apache.wss4j.crypto.merlin.keystore.type=jks\n";
+
+ try (FileOutputStream out = new FileOutputStream(tmp)) {
+ out.write(props.getBytes(StandardCharsets.UTF_8));
+ }
+
+ Crypto crypto = CryptoLoader.loadCryptoFromURL(tmp.toURI().toURL());
+ assertNotNull(crypto);
+ }
+
+ @Test(expected = WSSecurityException.class)
+ public void testAllowedFileSchemeWithBadPropertiesFailsInCryptoFactory()
throws Exception {
+ File tmp = File.createTempFile("cxf-crypto-invalid", ".properties");
+ tmp.deleteOnExit();
+
+ try (FileOutputStream out = new FileOutputStream(tmp)) {
+
out.write("org.apache.wss4j.crypto.provider=bad.Provider\n".getBytes(StandardCharsets.UTF_8));
+ }
+
+ CryptoLoader.loadCryptoFromURL(tmp.toURI().toURL());
+ }
+}