This is an automated email from the ASF dual-hosted git repository.

coheigea pushed a commit to branch coheigea/jose
in repository https://gitbox.apache.org/repos/asf/cxf.git

commit 73fb30af7f58982c5920a029967efec2388a6f9b
Author: Colm O hEigeartaigh <[email protected]>
AuthorDate: Tue May 12 15:04:19 2026 +0100

    Tighten up where we can download resources for Jose from
---
 .../httpsignature/utils/KeyManagementUtils.java    | 22 +++++++++++++++++++++-
 .../cxf/rs/security/jose/common/JoseUtils.java     | 21 ++++++++++++++++++++-
 .../cxf/rs/security/jose/jwk/JwkUtilsTest.java     | 14 ++++++++++++++
 .../filters/JwsJwksJwtAccessTokenValidator.java    | 18 +++++++++++++++++-
 .../oauth2/services/AuthorizationMetadata.java     | 11 +++++++++--
 .../JwsJwksJwtAccessTokenValidatorTest.java        |  5 +++++
 6 files changed, 86 insertions(+), 5 deletions(-)

diff --git 
a/rt/rs/security/http-signature/src/main/java/org/apache/cxf/rs/security/httpsignature/utils/KeyManagementUtils.java
 
b/rt/rs/security/http-signature/src/main/java/org/apache/cxf/rs/security/httpsignature/utils/KeyManagementUtils.java
index 766ae28df7d..e4a4a77be6e 100644
--- 
a/rt/rs/security/http-signature/src/main/java/org/apache/cxf/rs/security/httpsignature/utils/KeyManagementUtils.java
+++ 
b/rt/rs/security/http-signature/src/main/java/org/apache/cxf/rs/security/httpsignature/utils/KeyManagementUtils.java
@@ -20,6 +20,7 @@ package org.apache.cxf.rs.security.httpsignature.utils;
 
 import java.io.File;
 import java.io.InputStream;
+import java.net.MalformedURLException;
 import java.net.URL;
 import java.security.KeyStore;
 import java.security.PrivateKey;
@@ -203,7 +204,7 @@ public final class KeyManagementUtils {
         } else {
             try {
                 url = new URL(loc);
-            } catch (Exception ex) {
+            } catch (MalformedURLException ex) {
                 // it can be either a classpath or file resource without a 
scheme
                 url = getClasspathResourceURL(loc, KeyManagementUtils.class, 
bus);
                 if (url == null) {
@@ -213,6 +214,9 @@ public final class KeyManagementUtils {
                     }
                 }
             }
+            if (url != null) {
+                checkSupportedResourceUrlScheme(url, loc);
+            }
         }
         if (url == null) {
             LOG.warning("No resource " + loc + " is available");
@@ -220,6 +224,22 @@ public final class KeyManagementUtils {
         return url;
     }
 
+    private static void checkSupportedResourceUrlScheme(URL url, String loc) {
+        String scheme = url.getProtocol();
+        if ("https".equalsIgnoreCase(scheme)
+            || "file".equalsIgnoreCase(scheme)
+            || "jar".equalsIgnoreCase(scheme)
+            || "zip".equalsIgnoreCase(scheme)
+            || "wsjar".equalsIgnoreCase(scheme)) {
+            return;
+        }
+        if ("http".equalsIgnoreCase(scheme)) {
+            throw new SignatureException("URL resource must use HTTPS: " + 
loc);
+        }
+        throw new SignatureException("URL scheme '" + scheme
+                                     + "' is not supported for HTTP signature 
resource loading: " + loc);
+    }
+
     private static URL getClasspathResourceURL(String path, Class<?> 
callingClass, Bus bus) {
         URL url = ClassLoaderUtils.getResource(path, callingClass);
         return url == null ? getResource(path, URL.class, bus) : url;
diff --git 
a/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/common/JoseUtils.java
 
b/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/common/JoseUtils.java
index 0b52a35ef95..2bfdfaa554a 100644
--- 
a/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/common/JoseUtils.java
+++ 
b/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/common/JoseUtils.java
@@ -21,6 +21,7 @@ package org.apache.cxf.rs.security.jose.common;
 import java.io.File;
 import java.io.IOException;
 import java.io.InputStream;
+import java.net.MalformedURLException;
 import java.net.URL;
 import java.nio.charset.StandardCharsets;
 import java.security.spec.AlgorithmParameterSpec;
@@ -176,7 +177,7 @@ public final class JoseUtils {
         } else {
             try {
                 url = new URL(loc);
-            } catch (Exception ex) {
+            } catch (MalformedURLException ex) {
                 // it can be either a classpath or file resource without a 
scheme
                 url = JoseUtils.getClasspathResourceURL(loc, JoseUtils.class, 
bus);
                 if (url == null) {
@@ -186,6 +187,9 @@ public final class JoseUtils {
                     }
                 }
             }
+            if (url != null) {
+                checkSupportedResourceUrlScheme(url, loc);
+            }
         }
         if (url == null) {
             LOG.warning("No resource " + loc + " is available");
@@ -193,6 +197,21 @@ public final class JoseUtils {
         return url;
     }
 
+    private static void checkSupportedResourceUrlScheme(URL url, String loc) 
throws IOException {
+        String scheme = url.getProtocol();
+        if ("https".equalsIgnoreCase(scheme)
+            || "file".equalsIgnoreCase(scheme)
+            || "jar".equalsIgnoreCase(scheme)
+            || "zip".equalsIgnoreCase(scheme)
+            || "wsjar".equalsIgnoreCase(scheme)) {
+            return;
+        }
+        if ("http".equalsIgnoreCase(scheme)) {
+            throw new IOException("URL resource must use HTTPS: " + loc);
+        }
+        throw new IOException("URL scheme '" + scheme + "' is not supported 
for JOSE resource loading: " + loc);
+    }
+
     public static URL getClasspathResourceURL(String path, Class<?> 
callingClass, Bus bus) {
         URL url = ClassLoaderUtils.getResource(path, callingClass);
         return url == null ? getResource(path, URL.class, bus) : url;
diff --git 
a/rt/rs/security/jose-parent/jose/src/test/java/org/apache/cxf/rs/security/jose/jwk/JwkUtilsTest.java
 
b/rt/rs/security/jose-parent/jose/src/test/java/org/apache/cxf/rs/security/jose/jwk/JwkUtilsTest.java
index f7f30daccbb..68818d71501 100644
--- 
a/rt/rs/security/jose-parent/jose/src/test/java/org/apache/cxf/rs/security/jose/jwk/JwkUtilsTest.java
+++ 
b/rt/rs/security/jose-parent/jose/src/test/java/org/apache/cxf/rs/security/jose/jwk/JwkUtilsTest.java
@@ -39,6 +39,7 @@ import org.junit.Test;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
 
 public class JwkUtilsTest {
@@ -208,6 +209,19 @@ public class JwkUtilsTest {
         }
     }
 
+    @Test
+    public void testLoadPublicJwkSetRejectsHttpUrl() throws Exception {
+        final Properties props = new Properties();
+        props.setProperty(JoseConstants.RSSEC_KEY_STORE_FILE, 
"http://example.com/keys.jwks";);
+        try {
+            JwkUtils.loadPublicJwkSet(null, props);
+            fail();
+        } catch (JwkException e) {
+            assertNotNull(e.getCause());
+            assertTrue(e.getCause().getMessage().contains("must use HTTPS"));
+        }
+    }
+
     @Test
     public void testEcLeadingZeros() throws Exception {
         try (InputStream inputStream = 
this.getClass().getResourceAsStream("cert.pem")) {
diff --git 
a/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/filters/JwsJwksJwtAccessTokenValidator.java
 
b/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/filters/JwsJwksJwtAccessTokenValidator.java
index b9e22be589d..563d80aeb50 100644
--- 
a/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/filters/JwsJwksJwtAccessTokenValidator.java
+++ 
b/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/filters/JwsJwksJwtAccessTokenValidator.java
@@ -18,6 +18,8 @@
  */
 package org.apache.cxf.rs.security.oauth2.filters;
 
+import java.net.MalformedURLException;
+import java.net.URL;
 import java.util.Collections;
 import java.util.HashSet;
 import java.util.Map;
@@ -55,7 +57,7 @@ public class JwsJwksJwtAccessTokenValidator extends 
JwtAccessTokenValidator {
     }
 
     public void setJwksURL(String jwksURL) {
-        this.jwksURL = jwksURL;
+        this.jwksURL = validateJwksURL(jwksURL);
     }
 
     @Override
@@ -88,6 +90,20 @@ public class JwsJwksJwtAccessTokenValidator extends 
JwtAccessTokenValidator {
             .accept(MediaType.APPLICATION_JSON).get(JsonWebKeys.class);
     }
 
+    private static String validateJwksURL(String theJwksURL) {
+        Objects.requireNonNull(theJwksURL, "JWK Set URL must be specified");
+        final URL url;
+        try {
+            url = new URL(theJwksURL);
+        } catch (MalformedURLException ex) {
+            throw new IllegalArgumentException("Invalid JWK Set URL: " + 
theJwksURL, ex);
+        }
+        if (!"https".equalsIgnoreCase(url.getProtocol())) {
+            throw new IllegalArgumentException("JWK Set URL must use HTTPS 
scheme");
+        }
+        return theJwksURL;
+    }
+
     // from Java 11
     @SuppressWarnings("unchecked")
     static <T> Predicate<T> not(Predicate<? super T> target) {
diff --git 
a/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/services/AuthorizationMetadata.java
 
b/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/services/AuthorizationMetadata.java
index ad91bacea4c..eaa8febeb07 100644
--- 
a/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/services/AuthorizationMetadata.java
+++ 
b/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/services/AuthorizationMetadata.java
@@ -91,11 +91,11 @@ public class AuthorizationMetadata extends JsonMapObject {
     }
 
     public URL getJwksURL() {
-        return getURLProperty(JWKS_URI);
+        return checkHttpsScheme(getURLProperty(JWKS_URI), JWKS_URI);
     }
 
     public void setJwksURL(URL jwksURL) {
-        setURLProperty(JWKS_URI, jwksURL);
+        setURLProperty(JWKS_URI, checkHttpsScheme(jwksURL, JWKS_URI));
     }
 
     public URL getRegistrationEndpoint() {
@@ -263,4 +263,11 @@ public class AuthorizationMetadata extends JsonMapObject {
         super.setProperty(name, url != null ? url.toString() : null);
     }
 
+    private static URL checkHttpsScheme(URL url, String name) {
+        if (url != null && !"https".equalsIgnoreCase(url.getProtocol())) {
+            throw new IllegalArgumentException(name + " must use HTTPS 
scheme");
+        }
+        return url;
+    }
+
 }
diff --git 
a/rt/rs/security/oauth-parent/oauth2/src/test/java/org/apache/cxf/rs/security/oauth2/filters/JwsJwksJwtAccessTokenValidatorTest.java
 
b/rt/rs/security/oauth-parent/oauth2/src/test/java/org/apache/cxf/rs/security/oauth2/filters/JwsJwksJwtAccessTokenValidatorTest.java
index 71a21de2ee7..4a16a68ad1f 100644
--- 
a/rt/rs/security/oauth-parent/oauth2/src/test/java/org/apache/cxf/rs/security/oauth2/filters/JwsJwksJwtAccessTokenValidatorTest.java
+++ 
b/rt/rs/security/oauth-parent/oauth2/src/test/java/org/apache/cxf/rs/security/oauth2/filters/JwsJwksJwtAccessTokenValidatorTest.java
@@ -87,4 +87,9 @@ public class JwsJwksJwtAccessTokenValidatorTest {
         new 
JwsJwksJwtAccessTokenValidator().getInitializedSignatureVerifier(new 
JwsHeaders());
     }
 
+    @Test(expected = IllegalArgumentException.class)
+    public void testSetJwksURLRejectsHttp() {
+        new JwsJwksJwtAccessTokenValidator().setJwksURL("http://any.url";);
+    }
+
 }
\ No newline at end of file

Reply via email to