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

dengliming pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/shenyu.git


The following commit(s) were added to refs/heads/master by this push:
     new fcf0c98c34 fix: JWT plugin throws ArrayIndexOutOfBoundsException on 
malformed Authorization header (#6450)
fcf0c98c34 is described below

commit fcf0c98c34a22891eddeebbb0dfee99c27524c31
Author: wy471x <[email protected]>
AuthorDate: Fri Jul 31 17:43:47 2026 +0800

    fix: JWT plugin throws ArrayIndexOutOfBoundsException on malformed 
Authorization header (#6450)
    
    Use strict startsWith("Bearer ") check instead of contains("Bearer") and
    handle empty tokens gracefully instead of accessing split[1] directly.
    
    Co-authored-by: Claude Opus 4.7 <[email protected]>
    Co-authored-by: aias00 <[email protected]>
    Co-authored-by: xiaoyu <[email protected]>
    Co-authored-by: Liming Deng <[email protected]>
---
 .../org/apache/shenyu/plugin/jwt/JwtPlugin.java    | 16 +++---
 .../apache/shenyu/plugin/jwt/JwtPluginTest.java    | 62 ++++++++++++++++++++++
 2 files changed, 71 insertions(+), 7 deletions(-)

diff --git 
a/shenyu-plugin/shenyu-plugin-security/shenyu-plugin-jwt/src/main/java/org/apache/shenyu/plugin/jwt/JwtPlugin.java
 
b/shenyu-plugin/shenyu-plugin-security/shenyu-plugin-jwt/src/main/java/org/apache/shenyu/plugin/jwt/JwtPlugin.java
index 66847f6d2d..fff40be284 100644
--- 
a/shenyu-plugin/shenyu-plugin-security/shenyu-plugin-jwt/src/main/java/org/apache/shenyu/plugin/jwt/JwtPlugin.java
+++ 
b/shenyu-plugin/shenyu-plugin-security/shenyu-plugin-jwt/src/main/java/org/apache/shenyu/plugin/jwt/JwtPlugin.java
@@ -98,19 +98,21 @@ public class JwtPlugin extends AbstractShenyuPlugin {
      * @return the authorization after processing
      */
     private String compatible(final String token, final String authorization) {
-        String finalAuthorization;
         if (StringUtils.isNotEmpty(token)) {
-            finalAuthorization = token;
-        } else if (StringUtils.isNotEmpty(authorization)) {
-            finalAuthorization = authorization;
-        } else {
+            return token;
+        }
+        if (StringUtils.isEmpty(authorization)) {
             return null;
         }
-        return isAuth2(finalAuthorization) ? finalAuthorization.split(" ")[1] 
: finalAuthorization;
+        if (isAuth2(authorization)) {
+            String jwtToken = 
authorization.substring(AUTH2_TOKEN.length()).trim();
+            return StringUtils.isEmpty(jwtToken) ? null : jwtToken;
+        }
+        return authorization;
     }
 
     private boolean isAuth2(final String authorization) {
-        return authorization.contains(AUTH2_TOKEN);
+        return authorization.startsWith(AUTH2_TOKEN + " ");
     }
 
     /**
diff --git 
a/shenyu-plugin/shenyu-plugin-security/shenyu-plugin-jwt/src/test/java/org/apache/shenyu/plugin/jwt/JwtPluginTest.java
 
b/shenyu-plugin/shenyu-plugin-security/shenyu-plugin-jwt/src/test/java/org/apache/shenyu/plugin/jwt/JwtPluginTest.java
index 3c2daf4261..21e5a8d547 100644
--- 
a/shenyu-plugin/shenyu-plugin-security/shenyu-plugin-jwt/src/test/java/org/apache/shenyu/plugin/jwt/JwtPluginTest.java
+++ 
b/shenyu-plugin/shenyu-plugin-security/shenyu-plugin-jwt/src/test/java/org/apache/shenyu/plugin/jwt/JwtPluginTest.java
@@ -46,6 +46,7 @@ import java.util.Map;
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.argThat;
 import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
@@ -133,6 +134,67 @@ public final class JwtPluginTest {
         Assertions.assertEquals(PluginEnum.JWT.getCode(), result);
     }
 
+    @Test
+    public void testBearerWithoutToken() {
+        ServerWebExchange exchange = 
MockServerWebExchange.from(MockServerHttpRequest
+                .get("localhost")
+                .header("Authorization", "Bearer")
+                .build());
+
+        Mono<Void> mono = jwtPluginUnderTest.doExecute(exchange, chain, 
selectorData, ruleData);
+        StepVerifier.create(mono).expectSubscription().verifyComplete();
+        verify(chain, never()).execute(any());
+    }
+
+    @Test
+    public void testAuthorizationNotBearerPrefix() {
+        ServerWebExchange exchange = 
MockServerWebExchange.from(MockServerHttpRequest
+                .get("localhost")
+                .header("Authorization", "fooBearerbar")
+                .build());
+
+        Mono<Void> mono = jwtPluginUnderTest.doExecute(exchange, chain, 
selectorData, ruleData);
+        StepVerifier.create(mono).expectSubscription().verifyComplete();
+        verify(chain, never()).execute(any());
+    }
+
+    @Test
+    public void testBearerWithWhitespaceOnlyToken() {
+        ServerWebExchange exchange = 
MockServerWebExchange.from(MockServerHttpRequest
+                .get("localhost")
+                .header("Authorization", "Bearer  ")
+                .build());
+
+        Mono<Void> mono = jwtPluginUnderTest.doExecute(exchange, chain, 
selectorData, ruleData);
+        StepVerifier.create(mono).expectSubscription().verifyComplete();
+        verify(chain, never()).execute(any());
+    }
+
+    @Test
+    public void testValidBearerAuthorization() {
+        
ruleData.setHandle("{\"converter\":[{\"jwtVal\":\"userId\",\"headerVal\":\"id\"}]}");
+        jwtPluginDataHandlerUnderTest.handlerRule(ruleData);
+        when(chain.execute(any())).thenReturn(Mono.empty());
+
+        final String secreteKey = "shenyu-test-shenyu-test-shenyu-test";
+        Map<String, Object> map = ImmutableMap.<String, 
Object>builder().put("userId", 1).build();
+        String jwtToken = Jwts.builder()
+                .claims(map)
+                .issuedAt(new Date(1636371125000L))
+                .expiration(new Date(new Date().getTime() + 10000L))
+                
.signWith(Keys.hmacShaKeyFor(secreteKey.getBytes(StandardCharsets.UTF_8)))
+                .compact();
+
+        ServerWebExchange exchange = 
MockServerWebExchange.from(MockServerHttpRequest
+                .get("localhost")
+                .header("Authorization", "Bearer " + jwtToken)
+                .build());
+
+        Mono<Void> mono = jwtPluginUnderTest.doExecute(exchange, chain, 
selectorData, ruleData);
+        StepVerifier.create(mono).expectSubscription().verifyComplete();
+        verify(chain).execute(any());
+    }
+
     private void initContext() {
         ConfigurableApplicationContext context = 
mock(ConfigurableApplicationContext.class);
         when(context.getBean(ShenyuResult.class)).thenReturn(new 
DefaultShenyuResult());

Reply via email to