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

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


The following commit(s) were added to refs/heads/main by this push:
     new 942a663f30b Handle NaN or infinite times in JSON/JWT (#3137)
942a663f30b is described below

commit 942a663f30b677a644ce9e9dd7aa217e76cf50a0
Author: Colm O hEigeartaigh <[email protected]>
AuthorDate: Mon May 25 09:36:47 2026 +0100

    Handle NaN or infinite times in JSON/JWT (#3137)
---
 .../json/basic/JsonMapObjectReaderWriter.java      |  6 +++-
 .../json/basic/JsonMapObjectReaderWriterTest.java  | 22 ++++++++++++
 .../apache/cxf/rs/security/jose/jwt/JwtUtils.java  | 37 +++++++++++++++-----
 .../cxf/rs/security/jose/jwt/JwtUtilsTest.java     | 40 ++++++++++++++++++++++
 4 files changed, 95 insertions(+), 10 deletions(-)

diff --git 
a/rt/rs/extensions/json-basic/src/main/java/org/apache/cxf/jaxrs/json/basic/JsonMapObjectReaderWriter.java
 
b/rt/rs/extensions/json-basic/src/main/java/org/apache/cxf/jaxrs/json/basic/JsonMapObjectReaderWriter.java
index 88445b17e68..a99e7c43e73 100644
--- 
a/rt/rs/extensions/json-basic/src/main/java/org/apache/cxf/jaxrs/json/basic/JsonMapObjectReaderWriter.java
+++ 
b/rt/rs/extensions/json-basic/src/main/java/org/apache/cxf/jaxrs/json/basic/JsonMapObjectReaderWriter.java
@@ -258,7 +258,11 @@ public class JsonMapObjectReaderWriter {
             try {
                 value = Long.valueOf(valueStr);
             } catch (NumberFormatException ex) {
-                value = Double.valueOf(valueStr);
+                Double doubleValue = Double.valueOf(valueStr);
+                if (doubleValue.isInfinite() || doubleValue.isNaN()) {
+                    throw new NumberFormatException("Non-finite numeric value 
is not allowed");
+                }
+                value = doubleValue;
             }
         }
 
diff --git 
a/rt/rs/extensions/json-basic/src/test/java/org/apache/cxf/jaxrs/json/basic/JsonMapObjectReaderWriterTest.java
 
b/rt/rs/extensions/json-basic/src/test/java/org/apache/cxf/jaxrs/json/basic/JsonMapObjectReaderWriterTest.java
index 424eb72c5dd..9c66add08c1 100644
--- 
a/rt/rs/extensions/json-basic/src/test/java/org/apache/cxf/jaxrs/json/basic/JsonMapObjectReaderWriterTest.java
+++ 
b/rt/rs/extensions/json-basic/src/test/java/org/apache/cxf/jaxrs/json/basic/JsonMapObjectReaderWriterTest.java
@@ -33,6 +33,7 @@ import org.junit.Test;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
 
 public class JsonMapObjectReaderWriterTest {
 
@@ -210,4 +211,25 @@ public class JsonMapObjectReaderWriterTest {
         assertEquals("a\\", entry.getValue());
     }
 
+    @Test
+    public void testRejectInfinityNumericValue() {
+        assertInvalidNumericLiteral("Infinity");
+        assertInvalidNumericLiteral("-Infinity");
+    }
+
+    @Test
+    public void testRejectNaNNumericValue() {
+        assertInvalidNumericLiteral("NaN");
+    }
+
+    private void assertInvalidNumericLiteral(String value) {
+        JsonMapObjectReaderWriter jsonMapObjectReaderWriter = new 
JsonMapObjectReaderWriter();
+        try {
+            jsonMapObjectReaderWriter.fromJson("{\"exp\":" + value + "}");
+            fail("Expected NumberFormatException for invalid numeric value: " 
+ value);
+        } catch (NumberFormatException ex) {
+            // expected
+        }
+    }
+
 }
diff --git 
a/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jwt/JwtUtils.java
 
b/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jwt/JwtUtils.java
index 31653190db8..10b08220a93 100644
--- 
a/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jwt/JwtUtils.java
+++ 
b/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jwt/JwtUtils.java
@@ -50,9 +50,14 @@ public final class JwtUtils {
             return;
         }
         Instant now = Instant.now();
-        Instant expires = Instant.ofEpochMilli(expiryTime * 1000L);
-        if (clockOffset != 0) {
-            expires = expires.plusSeconds(clockOffset);
+        Instant expires;
+        try {
+            expires = Instant.ofEpochSecond(expiryTime);
+            if (clockOffset != 0) {
+                expires = expires.plusSeconds(clockOffset);
+            }
+        } catch (RuntimeException ex) {
+            throw new JwtException("The token has expired", ex);
         }
         if (expires.isBefore(now)) {
             throw new JwtException("The token has expired");
@@ -69,10 +74,15 @@ public final class JwtUtils {
         }
 
         Instant validCreation = Instant.now();
-        if (clockOffset != 0) {
-            validCreation = validCreation.plusSeconds(clockOffset);
+        Instant notBeforeDate;
+        try {
+            if (clockOffset != 0) {
+                validCreation = validCreation.plusSeconds(clockOffset);
+            }
+            notBeforeDate = Instant.ofEpochSecond(notBeforeTime);
+        } catch (RuntimeException ex) {
+            throw new JwtException("The token cannot be accepted yet", ex);
         }
-        Instant notBeforeDate = Instant.ofEpochMilli(notBeforeTime * 1000L);
 
         // Check to see if the not before time is in the future
         if (notBeforeDate.isAfter(validCreation)) {
@@ -89,11 +99,20 @@ public final class JwtUtils {
             return;
         }
 
-        Instant createdDate = Instant.ofEpochMilli(issuedAtInSecs * 1000L);
+        Instant createdDate;
+        try {
+            createdDate = Instant.ofEpochSecond(issuedAtInSecs);
+        } catch (RuntimeException ex) {
+            throw new JwtException("Invalid issuedAt", ex);
+        }
 
         Instant validCreation = Instant.now();
-        if (clockOffset != 0) {
-            validCreation = validCreation.plusSeconds(clockOffset);
+        try {
+            if (clockOffset != 0) {
+                validCreation = validCreation.plusSeconds(clockOffset);
+            }
+        } catch (RuntimeException ex) {
+            throw new JwtException("Invalid issuedAt", ex);
         }
 
         // Check to see if the IssuedAt time is in the future
diff --git 
a/rt/rs/security/jose-parent/jose/src/test/java/org/apache/cxf/rs/security/jose/jwt/JwtUtilsTest.java
 
b/rt/rs/security/jose-parent/jose/src/test/java/org/apache/cxf/rs/security/jose/jwt/JwtUtilsTest.java
index e53a47060c8..af58d2d0e7c 100644
--- 
a/rt/rs/security/jose-parent/jose/src/test/java/org/apache/cxf/rs/security/jose/jwt/JwtUtilsTest.java
+++ 
b/rt/rs/security/jose-parent/jose/src/test/java/org/apache/cxf/rs/security/jose/jwt/JwtUtilsTest.java
@@ -174,4 +174,44 @@ public class JwtUtilsTest {
         }
     }
 
+    @org.junit.Test
+    public void testInfiniteExpiryTokenRejected() {
+        try {
+            String claimsJson = 
"{\"sub\":\"alice\",\"iss\":\"DoubleItSTSIssuer\","
+                + "\"exp\":Infinity}";
+            JwtClaims claims = JwtUtils.jsonToClaims(claimsJson);
+            JwtUtils.validateJwtExpiry(claims, 0, true);
+            fail("Failure expected on a token with infinite expiry");
+        } catch (JwtException | NumberFormatException ex) {
+            // expected
+        }
+    }
+
+    @org.junit.Test
+    public void testInfiniteNotBeforeTokenRejected() {
+        try {
+            String claimsJson = 
"{\"sub\":\"alice\",\"iss\":\"DoubleItSTSIssuer\","
+                + "\"nbf\":Infinity}";
+            JwtClaims claims = JwtUtils.jsonToClaims(claimsJson);
+            JwtUtils.validateJwtNotBefore(claims, 0, true);
+            fail("Failure expected on a token with infinite not before");
+        } catch (JwtException | NumberFormatException ex) {
+            // expected
+        }
+    }
+
+    @org.junit.Test
+    public void testInfiniteIssuedAtTokenRejected() {
+        try {
+            String claimsJson = 
"{\"sub\":\"alice\",\"iss\":\"DoubleItSTSIssuer\","
+                + "\"iat\":Infinity}";
+            JwtClaims claims = JwtUtils.jsonToClaims(claimsJson);
+            JwtUtils.validateJwtIssuedAt(claims, 0, 0, true);
+            fail("Failure expected on a token with infinite issued at");
+        } catch (JwtException | NumberFormatException ex) {
+            // expected
+        }
+    }
+
+
 }

Reply via email to