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

jimin pushed a commit to branch 2.x
in repository https://gitbox.apache.org/repos/asf/incubator-seata.git


The following commit(s) were added to refs/heads/2.x by this push:
     new 36dd48e08f bugfix: fix deserialization failure when the XSS filter 
retrieved the default keyword (#7596)
36dd48e08f is described below

commit 36dd48e08f8f529b08b49ab794d98265c3dff1a7
Author: xiaoyu <[email protected]>
AuthorDate: Wed Aug 27 11:12:01 2025 +0800

    bugfix: fix deserialization failure when the XSS filter retrieved the 
default keyword (#7596)
---
 changes/en-us/2.x.md                               |  1 +
 changes/zh-cn/2.x.md                               |  1 +
 .../org/apache/seata/common/ConfigurationKeys.java | 10 -----
 .../http/filter/HttpRequestFilterManager.java      | 18 ++++-----
 .../http/filter/HttpRequestFilterManagerTest.java  | 32 +++------------
 script/config-center/config.txt                    |  2 -
 .../SeataServerEnvironmentPostProcessor.java       |  3 --
 .../server/filter/ServerHttpFilterProperties.java  | 36 -----------------
 .../filter/ServerHttpFilterXssProperties.java      | 19 ++-------
 .../filter/ServerHttpFilterPropertiesTest.java     | 38 ------------------
 .../filter/ServerHttpFilterXssPropertiesTest.java  | 16 ++------
 .../seata/server/filter/XSSHttpRequestFilter.java  | 46 ++++++++++++++--------
 server/src/main/resources/application.example.yml  |  2 -
 .../main/resources/application.raft.example.yml    |  2 -
 .../server/controller/ClusterControllerTest.java   | 16 ++++++++
 server/src/test/resources/application.properties   |  2 +-
 16 files changed, 70 insertions(+), 174 deletions(-)

diff --git a/changes/en-us/2.x.md b/changes/en-us/2.x.md
index 67d8bb70ca..9f40c31479 100644
--- a/changes/en-us/2.x.md
+++ b/changes/en-us/2.x.md
@@ -33,6 +33,7 @@ Add changes here for all PR submitted to the 2.x branch.
 - [[#7505](https://github.com/apache/incubator-seata/pull/7505)] prevent Netty 
I/O thread blocking by async channel release via reconnectExecutor
 - [[#7563](https://github.com/apache/incubator-seata/pull/7563)] Fix NPE when 
server-side filter is disabled and filter chain is null.
 - [[#7568](https://github.com/apache/incubator-seata/pull/7568)] Fix order() 
behavior in GlobalTransactionalInterceptorHandler to ensure correct sorting of 
invocation handlers
+- [[#7596](https://github.com/apache/incubator-seata/pull/7596)] Fixed the 
issue where deserialization failed when the xss filter obtained the default 
keyword
 
 
 
diff --git a/changes/zh-cn/2.x.md b/changes/zh-cn/2.x.md
index 5aeef15e73..c9ecefde52 100644
--- a/changes/zh-cn/2.x.md
+++ b/changes/zh-cn/2.x.md
@@ -33,6 +33,7 @@
 - [[#7505](https://github.com/apache/incubator-seata/pull/7505)] 通过使用 
reconnectExecutor 异步释放 channel,防止阻塞 Netty I/O 线程
 - [[#7563](https://github.com/apache/incubator-seata/pull/7563)] 
修复在未开启服务端过滤器的状态下导致的过滤器链空指针异常
 - [[#7568](https://github.com/apache/incubator-seata/pull/7568)] 修复 
GlobalTransactionalInterceptorHandler 中的 order() 方法行为,确保拦截器的正确排序
+- [[#7596](https://github.com/apache/incubator-seata/pull/7596)] 
修复xss过滤器获取默认关键字时反序列化失败的问题
 
 
 ### optimize:
diff --git 
a/common/src/main/java/org/apache/seata/common/ConfigurationKeys.java 
b/common/src/main/java/org/apache/seata/common/ConfigurationKeys.java
index f8433e3448..2eb5fe3e2f 100644
--- a/common/src/main/java/org/apache/seata/common/ConfigurationKeys.java
+++ b/common/src/main/java/org/apache/seata/common/ConfigurationKeys.java
@@ -1142,16 +1142,6 @@ public interface ConfigurationKeys {
 
     String SERVER_HTTP_FILTER_PREFIX = SERVER_HTTP + "filter.";
 
-    /**
-     * The constant SERVER_HTTP_FILTERS_ENABLED.
-     */
-    String SERVER_HTTP_FILTER_ENABLE = SERVER_HTTP_FILTER_PREFIX + "enabled";
-
-    /**
-     * The constant SERVER_HTTP_FILTER_XSS_ENABLED.
-     */
-    String SERVER_HTTP_FILTER_XSS_FILTER_ENABLE = SERVER_HTTP_FILTER_PREFIX + 
"xss.enabled";
-
     /**
      * The constant SERVER_HTTP_FILTER_XSS_FILTER_KEYWORDS.
      *
diff --git 
a/core/src/main/java/org/apache/seata/core/rpc/netty/http/filter/HttpRequestFilterManager.java
 
b/core/src/main/java/org/apache/seata/core/rpc/netty/http/filter/HttpRequestFilterManager.java
index e4975864d2..5099a60652 100644
--- 
a/core/src/main/java/org/apache/seata/core/rpc/netty/http/filter/HttpRequestFilterManager.java
+++ 
b/core/src/main/java/org/apache/seata/core/rpc/netty/http/filter/HttpRequestFilterManager.java
@@ -17,8 +17,6 @@
 package org.apache.seata.core.rpc.netty.http.filter;
 
 import org.apache.seata.common.loader.EnhancedServiceLoader;
-import org.apache.seata.config.ConfigurationFactory;
-import org.apache.seata.config.ConfigurationKeys;
 
 import java.util.ArrayList;
 import java.util.Comparator;
@@ -35,17 +33,15 @@ public class HttpRequestFilterManager {
         if (initialized) {
             return;
         }
-        boolean enableFilter =
-                
ConfigurationFactory.getInstance().getBoolean(ConfigurationKeys.SERVER_HTTP_FILTER_ENABLE,
 true);
-        if (enableFilter) {
-            List<HttpRequestFilter> httpRequestFilters = 
EnhancedServiceLoader.loadAll(HttpRequestFilter.class);
-            for (HttpRequestFilter filter : httpRequestFilters) {
-                if (filter.shouldApply()) {
-                    HTTP_REQUEST_FILTERS.add(filter);
-                }
+
+        List<HttpRequestFilter> httpRequestFilters = 
EnhancedServiceLoader.loadAll(HttpRequestFilter.class);
+        for (HttpRequestFilter filter : httpRequestFilters) {
+            if (filter.shouldApply()) {
+                HTTP_REQUEST_FILTERS.add(filter);
             }
-            
HTTP_REQUEST_FILTERS.sort(Comparator.comparingInt(HttpRequestFilter::getOrder));
         }
+        
HTTP_REQUEST_FILTERS.sort(Comparator.comparingInt(HttpRequestFilter::getOrder));
+
         HTTP_REQUEST_FILTER_CHAIN = new 
HttpRequestFilterChain(HTTP_REQUEST_FILTERS);
         initialized = true;
     }
diff --git 
a/core/src/test/java/org/apache/seata/core/rpc/netty/http/filter/HttpRequestFilterManagerTest.java
 
b/core/src/test/java/org/apache/seata/core/rpc/netty/http/filter/HttpRequestFilterManagerTest.java
index d30f53caa0..a68bc9d6b6 100644
--- 
a/core/src/test/java/org/apache/seata/core/rpc/netty/http/filter/HttpRequestFilterManagerTest.java
+++ 
b/core/src/test/java/org/apache/seata/core/rpc/netty/http/filter/HttpRequestFilterManagerTest.java
@@ -16,10 +16,7 @@
  */
 package org.apache.seata.core.rpc.netty.http.filter;
 
-import org.apache.seata.common.ConfigurationKeys;
 import org.apache.seata.common.loader.EnhancedServiceLoader;
-import org.apache.seata.config.Configuration;
-import org.apache.seata.config.ConfigurationFactory;
 import org.junit.jupiter.api.AfterEach;
 import org.junit.jupiter.api.Test;
 import org.mockito.MockedStatic;
@@ -67,13 +64,7 @@ class HttpRequestFilterManagerTest {
         when(filter2.shouldApply()).thenReturn(true);
         when(filter2.getOrder()).thenReturn(5);
 
-        try (MockedStatic<ConfigurationFactory> configMock = 
mockStatic(ConfigurationFactory.class);
-                MockedStatic<EnhancedServiceLoader> mockedLoader = 
mockStatic(EnhancedServiceLoader.class)) {
-
-            Configuration mockConfig = mock(Configuration.class);
-            
when(mockConfig.getBoolean(ConfigurationKeys.SERVER_HTTP_FILTER_ENABLE, true))
-                    .thenReturn(true);
-            
configMock.when(ConfigurationFactory::getInstance).thenReturn(mockConfig);
+        try (MockedStatic<EnhancedServiceLoader> mockedLoader = 
mockStatic(EnhancedServiceLoader.class)) {
 
             mockedLoader
                     .when(() -> 
EnhancedServiceLoader.loadAll(HttpRequestFilter.class))
@@ -100,12 +91,7 @@ class HttpRequestFilterManagerTest {
         MockFilter filter = mock(MockFilter.class);
         when(filter.shouldApply()).thenReturn(false);
 
-        try (MockedStatic<ConfigurationFactory> configMock = 
mockStatic(ConfigurationFactory.class);
-                MockedStatic<EnhancedServiceLoader> mockedLoader = 
mockStatic(EnhancedServiceLoader.class)) {
-            Configuration mockConfig = mock(Configuration.class);
-            
when(mockConfig.getBoolean(ConfigurationKeys.SERVER_HTTP_FILTER_ENABLE, true))
-                    .thenReturn(true);
-            
configMock.when(ConfigurationFactory::getInstance).thenReturn(mockConfig);
+        try (MockedStatic<EnhancedServiceLoader> mockedLoader = 
mockStatic(EnhancedServiceLoader.class)) {
             mockedLoader
                     .when(() -> 
EnhancedServiceLoader.loadAll(HttpRequestFilter.class))
                     .thenReturn(Arrays.asList(filter));
@@ -123,17 +109,11 @@ class HttpRequestFilterManagerTest {
         MockFilter filter = mock(MockFilter.class);
         when(filter.shouldApply()).thenReturn(true);
 
-        try (MockedStatic<ConfigurationFactory> configMock = 
mockStatic(ConfigurationFactory.class)) {
-            Configuration mockConfig = mock(Configuration.class);
-            
when(mockConfig.getBoolean(ConfigurationKeys.SERVER_HTTP_FILTER_ENABLE, true))
-                    .thenReturn(false);
-            
configMock.when(ConfigurationFactory::getInstance).thenReturn(mockConfig);
-            HttpRequestFilterManager.initializeFilters();
+        HttpRequestFilterManager.initializeFilters();
 
-            HttpRequestFilterChain chain = 
HttpRequestFilterManager.getFilterChain();
-            assertNotNull(chain);
-            assertTrue(chain.getFilters().isEmpty(), "Filters list should be 
empty when filter config is false");
-        }
+        HttpRequestFilterChain chain = 
HttpRequestFilterManager.getFilterChain();
+        assertNotNull(chain);
+        assertTrue(chain.getFilters().isEmpty(), "Filters list should be empty 
when filter config is false");
     }
 
     @Test
diff --git a/script/config-center/config.txt b/script/config-center/config.txt
index c4cad2070c..4c9e5c43a2 100644
--- a/script/config-center/config.txt
+++ b/script/config-center/config.txt
@@ -205,8 +205,6 @@ server.ratelimit.bucketTokenNumPerSecond = 999999
 server.ratelimit.bucketTokenMaxNum = 999999
 server.ratelimit.bucketTokenInitialNum = 999999
 
-server.http.filter.enabled=true
-server.http.filter.xss.enabled=true
 server.http.filter.xss.keywords=["<script>", "</script>", "javascript:", 
"vbscript:"]
 
 #Metrics configuration, only for the server
diff --git 
a/seata-spring-autoconfigure/seata-spring-autoconfigure-server/src/main/java/org/apache/seata/spring/boot/autoconfigure/SeataServerEnvironmentPostProcessor.java
 
b/seata-spring-autoconfigure/seata-spring-autoconfigure-server/src/main/java/org/apache/seata/spring/boot/autoconfigure/SeataServerEnvironmentPostProcessor.java
index 008cb38ef7..d0365d09b8 100644
--- 
a/seata-spring-autoconfigure/seata-spring-autoconfigure-server/src/main/java/org/apache/seata/spring/boot/autoconfigure/SeataServerEnvironmentPostProcessor.java
+++ 
b/seata-spring-autoconfigure/seata-spring-autoconfigure-server/src/main/java/org/apache/seata/spring/boot/autoconfigure/SeataServerEnvironmentPostProcessor.java
@@ -21,7 +21,6 @@ import 
org.apache.seata.spring.boot.autoconfigure.properties.server.ServerProper
 import 
org.apache.seata.spring.boot.autoconfigure.properties.server.ServerRateLimitProperties;
 import 
org.apache.seata.spring.boot.autoconfigure.properties.server.ServerRecoveryProperties;
 import 
org.apache.seata.spring.boot.autoconfigure.properties.server.ServerUndoProperties;
-import 
org.apache.seata.spring.boot.autoconfigure.properties.server.filter.ServerHttpFilterProperties;
 import 
org.apache.seata.spring.boot.autoconfigure.properties.server.filter.ServerHttpFilterXssProperties;
 import 
org.apache.seata.spring.boot.autoconfigure.properties.server.raft.ServerRaftProperties;
 import 
org.apache.seata.spring.boot.autoconfigure.properties.server.raft.ServerRaftSSLClientProperties;
@@ -46,7 +45,6 @@ import java.util.concurrent.atomic.AtomicBoolean;
 
 import static 
org.apache.seata.spring.boot.autoconfigure.StarterConstants.METRICS_PREFIX;
 import static 
org.apache.seata.spring.boot.autoconfigure.StarterConstants.PROPERTY_BEAN_MAP;
-import static 
org.apache.seata.spring.boot.autoconfigure.StarterConstants.SERVER_HTTP_FILTER_PREFIX;
 import static 
org.apache.seata.spring.boot.autoconfigure.StarterConstants.SERVER_HTTP_FILTER_XSS_PREFIX;
 import static 
org.apache.seata.spring.boot.autoconfigure.StarterConstants.SERVER_PREFIX;
 import static 
org.apache.seata.spring.boot.autoconfigure.StarterConstants.SERVER_RAFT_PREFIX;
@@ -106,7 +104,6 @@ public class SeataServerEnvironmentPostProcessor implements 
EnvironmentPostProce
             PROPERTY_BEAN_MAP.put(SESSION_PREFIX, SessionProperties.class);
             PROPERTY_BEAN_MAP.put(STORE_PREFIX, StoreProperties.class);
             PROPERTY_BEAN_MAP.put(SERVER_RATELIMIT_PREFIX, 
ServerRateLimitProperties.class);
-            PROPERTY_BEAN_MAP.put(SERVER_HTTP_FILTER_PREFIX, 
ServerHttpFilterProperties.class);
             PROPERTY_BEAN_MAP.put(SERVER_HTTP_FILTER_XSS_PREFIX, 
ServerHttpFilterXssProperties.class);
         }
     }
diff --git 
a/seata-spring-autoconfigure/seata-spring-autoconfigure-server/src/main/java/org/apache/seata/spring/boot/autoconfigure/properties/server/filter/ServerHttpFilterProperties.java
 
b/seata-spring-autoconfigure/seata-spring-autoconfigure-server/src/main/java/org/apache/seata/spring/boot/autoconfigure/properties/server/filter/ServerHttpFilterProperties.java
deleted file mode 100644
index 01cfc1b4a9..0000000000
--- 
a/seata-spring-autoconfigure/seata-spring-autoconfigure-server/src/main/java/org/apache/seata/spring/boot/autoconfigure/properties/server/filter/ServerHttpFilterProperties.java
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * 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.seata.spring.boot.autoconfigure.properties.server.filter;
-
-import org.springframework.boot.context.properties.ConfigurationProperties;
-import org.springframework.stereotype.Component;
-
-import static 
org.apache.seata.spring.boot.autoconfigure.StarterConstants.SERVER_HTTP_FILTER_PREFIX;
-
-@Component
-@ConfigurationProperties(prefix = SERVER_HTTP_FILTER_PREFIX)
-public class ServerHttpFilterProperties {
-    private boolean enabled = true;
-
-    public boolean isEnabled() {
-        return enabled;
-    }
-
-    public void setEnabled(boolean enabled) {
-        this.enabled = enabled;
-    }
-}
diff --git 
a/seata-spring-autoconfigure/seata-spring-autoconfigure-server/src/main/java/org/apache/seata/spring/boot/autoconfigure/properties/server/filter/ServerHttpFilterXssProperties.java
 
b/seata-spring-autoconfigure/seata-spring-autoconfigure-server/src/main/java/org/apache/seata/spring/boot/autoconfigure/properties/server/filter/ServerHttpFilterXssProperties.java
index f620ae57ae..977110f4d0 100644
--- 
a/seata-spring-autoconfigure/seata-spring-autoconfigure-server/src/main/java/org/apache/seata/spring/boot/autoconfigure/properties/server/filter/ServerHttpFilterXssProperties.java
+++ 
b/seata-spring-autoconfigure/seata-spring-autoconfigure-server/src/main/java/org/apache/seata/spring/boot/autoconfigure/properties/server/filter/ServerHttpFilterXssProperties.java
@@ -19,31 +19,20 @@ package 
org.apache.seata.spring.boot.autoconfigure.properties.server.filter;
 import org.springframework.boot.context.properties.ConfigurationProperties;
 import org.springframework.stereotype.Component;
 
-import java.util.List;
-
-import static org.apache.seata.common.DefaultValues.DEFAULT_XSS_KEYWORDS;
 import static 
org.apache.seata.spring.boot.autoconfigure.StarterConstants.SERVER_HTTP_FILTER_XSS_PREFIX;
 
 @Component
 @ConfigurationProperties(prefix = SERVER_HTTP_FILTER_XSS_PREFIX)
 public class ServerHttpFilterXssProperties {
-    private boolean enabled = true;
-
-    private List<String> keywords = DEFAULT_XSS_KEYWORDS;
 
-    public boolean isEnabled() {
-        return enabled;
-    }
-
-    public void setEnabled(boolean enabled) {
-        this.enabled = enabled;
-    }
+    // It is specified by the user
+    private String keywords;
 
-    public List<String> getKeywords() {
+    public String getKeywords() {
         return keywords;
     }
 
-    public void setKeywords(List<String> keywords) {
+    public void setKeywords(String keywords) {
         this.keywords = keywords;
     }
 }
diff --git 
a/seata-spring-autoconfigure/seata-spring-autoconfigure-server/src/test/java/org/apache/seata/spring/boot/autoconfigure/properties/server/filter/ServerHttpFilterPropertiesTest.java
 
b/seata-spring-autoconfigure/seata-spring-autoconfigure-server/src/test/java/org/apache/seata/spring/boot/autoconfigure/properties/server/filter/ServerHttpFilterPropertiesTest.java
deleted file mode 100644
index 3380e4c1a1..0000000000
--- 
a/seata-spring-autoconfigure/seata-spring-autoconfigure-server/src/test/java/org/apache/seata/spring/boot/autoconfigure/properties/server/filter/ServerHttpFilterPropertiesTest.java
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * 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.seata.spring.boot.autoconfigure.properties.server.filter;
-
-import org.junit.jupiter.api.Assertions;
-import org.junit.jupiter.api.Test;
-
-public class ServerHttpFilterPropertiesTest {
-
-    @Test
-    public void testServerHttpFilterProperties() {
-        ServerHttpFilterProperties serverHttpFilterProperties = new 
ServerHttpFilterProperties();
-
-        Assertions.assertTrue(serverHttpFilterProperties.isEnabled());
-    }
-
-    @Test
-    public void testServerHttpFilterPropertiesUnDefaultValue() {
-        ServerHttpFilterProperties serverHttpFilterProperties = new 
ServerHttpFilterProperties();
-        serverHttpFilterProperties.setEnabled(false);
-
-        Assertions.assertFalse(serverHttpFilterProperties.isEnabled());
-    }
-}
diff --git 
a/seata-spring-autoconfigure/seata-spring-autoconfigure-server/src/test/java/org/apache/seata/spring/boot/autoconfigure/properties/server/filter/ServerHttpFilterXssPropertiesTest.java
 
b/seata-spring-autoconfigure/seata-spring-autoconfigure-server/src/test/java/org/apache/seata/spring/boot/autoconfigure/properties/server/filter/ServerHttpFilterXssPropertiesTest.java
index f7f4bb66e1..6d850c794e 100644
--- 
a/seata-spring-autoconfigure/seata-spring-autoconfigure-server/src/test/java/org/apache/seata/spring/boot/autoconfigure/properties/server/filter/ServerHttpFilterXssPropertiesTest.java
+++ 
b/seata-spring-autoconfigure/seata-spring-autoconfigure-server/src/test/java/org/apache/seata/spring/boot/autoconfigure/properties/server/filter/ServerHttpFilterXssPropertiesTest.java
@@ -16,31 +16,23 @@
  */
 package org.apache.seata.spring.boot.autoconfigure.properties.server.filter;
 
+import org.apache.seata.common.util.StringUtils;
 import org.junit.jupiter.api.Assertions;
 import org.junit.jupiter.api.Test;
 
-import java.util.Collections;
-
 public class ServerHttpFilterXssPropertiesTest {
     @Test
     public void testServerHttpFilterXssProperties() {
         ServerHttpFilterXssProperties serverHttpFilterXssProperties = new 
ServerHttpFilterXssProperties();
 
-        Assertions.assertTrue(serverHttpFilterXssProperties.isEnabled());
-        Assertions.assertEquals(
-                "<script>", 
serverHttpFilterXssProperties.getKeywords().get(0));
+        
Assertions.assertTrue(StringUtils.isBlank(serverHttpFilterXssProperties.getKeywords()));
     }
 
     @Test
     public void testServerHttpFilterPropertiesUnDefaultValue() {
         ServerHttpFilterXssProperties serverHttpFilterXssProperties = new 
ServerHttpFilterXssProperties();
 
-        serverHttpFilterXssProperties.setEnabled(false);
-
-        
serverHttpFilterXssProperties.setKeywords(Collections.singletonList("<alert>"));
-
-        Assertions.assertFalse(serverHttpFilterXssProperties.isEnabled());
-        Assertions.assertEquals(
-                "<alert>", serverHttpFilterXssProperties.getKeywords().get(0));
+        serverHttpFilterXssProperties.setKeywords("<alert>");
+        
Assertions.assertTrue(serverHttpFilterXssProperties.getKeywords().contains("<alert>"));
     }
 }
diff --git 
a/server/src/main/java/org/apache/seata/server/filter/XSSHttpRequestFilter.java 
b/server/src/main/java/org/apache/seata/server/filter/XSSHttpRequestFilter.java
index 3c6c9ded0e..baaee393af 100644
--- 
a/server/src/main/java/org/apache/seata/server/filter/XSSHttpRequestFilter.java
+++ 
b/server/src/main/java/org/apache/seata/server/filter/XSSHttpRequestFilter.java
@@ -20,16 +20,20 @@ import com.fasterxml.jackson.core.JsonProcessingException;
 import com.fasterxml.jackson.core.type.TypeReference;
 import com.fasterxml.jackson.databind.ObjectMapper;
 import org.apache.seata.common.loader.LoadLevel;
+import org.apache.seata.common.util.CollectionUtils;
 import org.apache.seata.common.util.StringUtils;
 import org.apache.seata.config.Configuration;
 import org.apache.seata.config.ConfigurationFactory;
-import org.apache.seata.config.ConfigurationKeys;
 import org.apache.seata.core.exception.HttpRequestFilterException;
 import org.apache.seata.core.rpc.netty.http.filter.HttpFilterContext;
 import org.apache.seata.core.rpc.netty.http.filter.HttpRequestFilter;
 
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.LinkedHashSet;
 import java.util.List;
 import java.util.Map;
+import java.util.Set;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
@@ -46,7 +50,7 @@ public class XSSHttpRequestFilter implements 
HttpRequestFilter {
      */
     private static final Configuration CONFIG = 
ConfigurationFactory.getInstance();
 
-    private final List<String> xssKeywords;
+    private static List<String> xssKeywords = DEFAULT_XSS_KEYWORDS;
 
     private static final int MAX_EVENT_HANDLER_LENGTH = 50;
 
@@ -63,18 +67,29 @@ public class XSSHttpRequestFilter implements 
HttpRequestFilter {
         String xssKeywordConfig = 
CONFIG.getConfig(SERVER_HTTP_FILTER_XSS_FILTER_KEYWORDS, null);
 
         if (StringUtils.isBlank(xssKeywordConfig)) {
-            this.xssKeywords = DEFAULT_XSS_KEYWORDS;
-        } else {
-            ObjectMapper objectMapper = new ObjectMapper();
-            try {
-                xssKeywords = objectMapper.readValue(xssKeywordConfig, new 
TypeReference<List<String>>() {});
-            } catch (JsonProcessingException e) {
-                throw new IllegalArgumentException(
-                        "Invalid format for configuration 
'server.http.filter.xss.keywords'. "
-                                + "Expected a JSON array like [\"<script>\", 
\"vbscript:\"], but got: "
-                                + xssKeywordConfig,
-                        e);
+            return;
+        }
+
+        ObjectMapper objectMapper = new ObjectMapper();
+        try {
+            List<String> userCustomKeywords =
+                    objectMapper.readValue(xssKeywordConfig, new 
TypeReference<List<String>>() {});
+            Set<String> mergedKeywords = new 
LinkedHashSet<>(DEFAULT_XSS_KEYWORDS);
+            if (CollectionUtils.isNotEmpty(userCustomKeywords)) {
+                mergedKeywords.addAll(userCustomKeywords);
             }
+
+            // Use an unmodifiable list to ensure that XSS keyword 
configurations
+            // remain read-only after initialization, preventing accidental or
+            // malicious modifications at runtime.
+            this.xssKeywords = Collections.unmodifiableList(new 
ArrayList<>(mergedKeywords));
+
+        } catch (JsonProcessingException e) {
+            throw new IllegalArgumentException(
+                    "Invalid format for configuration 
'server.http.filter.xss.keywords'. "
+                            + "Expected a JSON array like [\"<script>\", 
\"vbscript:\"], but got: "
+                            + xssKeywordConfig,
+                    e);
         }
     }
 
@@ -100,12 +115,11 @@ public class XSSHttpRequestFilter implements 
HttpRequestFilter {
     }
 
     /**
-     * Returns whether this XSS filter is enabled via configuration.
+     * The system is forcibly enabled by default
      */
     @Override
     public boolean shouldApply() {
-        return ConfigurationFactory.getInstance()
-                
.getBoolean(ConfigurationKeys.SERVER_HTTP_FILTER_XSS_FILTER_ENABLE, true);
+        return true;
     }
 
     /**
diff --git a/server/src/main/resources/application.example.yml 
b/server/src/main/resources/application.example.yml
index 0bfb0c6bfe..1585122291 100644
--- a/server/src/main/resources/application.example.yml
+++ b/server/src/main/resources/application.example.yml
@@ -176,9 +176,7 @@ seata:
       bucketTokenInitialNum: 999999
     http:
       filter:
-        enabled: true
         xss:
-          enabled: true
           keywords: ["<script>", "</script>", "javascript:", "vbscript:"]
   store:
     # support: file 、 db 、 redis 、 raft
diff --git a/server/src/main/resources/application.raft.example.yml 
b/server/src/main/resources/application.raft.example.yml
index fa78e36af3..a337e80ba4 100644
--- a/server/src/main/resources/application.raft.example.yml
+++ b/server/src/main/resources/application.raft.example.yml
@@ -152,9 +152,7 @@ seata:
       bucketTokenInitialNum: 999999
     http:
       filter:
-        enabled: true
         xss:
-          enabled: true
           keywords: ["<script>", "</script>", "javascript:", "vbscript:"]
   store:
     # support: file
diff --git 
a/server/src/test/java/org/apache/seata/server/controller/ClusterControllerTest.java
 
b/server/src/test/java/org/apache/seata/server/controller/ClusterControllerTest.java
index 18dc5d867d..5c3b360db2 100644
--- 
a/server/src/test/java/org/apache/seata/server/controller/ClusterControllerTest.java
+++ 
b/server/src/test/java/org/apache/seata/server/controller/ClusterControllerTest.java
@@ -189,4 +189,20 @@ class ClusterControllerTest extends BaseSpringBootTest {
                     HttpStatus.SC_BAD_REQUEST, 
response.getStatusLine().getStatusCode());
         }
     }
+
+    @Test
+    @Order(8)
+    void testXssFilterBlocked_formParamWithUserCustomKeyWords() throws 
Exception {
+        Map<String, String> headers = new HashMap<>();
+        headers.put(HTTP.CONTENT_TYPE, 
ContentType.APPLICATION_FORM_URLENCODED.getMimeType());
+
+        Map<String, String> params = new HashMap<>();
+        params.put("testParam", "custom1");
+
+        try (CloseableHttpResponse response = HttpClientUtil.doPost(
+                "http://127.0.0.1:"; + port + 
"/metadata/v1/watch?timeout=3000", params, headers, 5000)) {
+            Assertions.assertEquals(
+                    HttpStatus.SC_BAD_REQUEST, 
response.getStatusLine().getStatusCode());
+        }
+    }
 }
diff --git a/server/src/test/resources/application.properties 
b/server/src/test/resources/application.properties
index 5fb3e7abfa..b7fec4d62d 100644
--- a/server/src/test/resources/application.properties
+++ b/server/src/test/resources/application.properties
@@ -23,4 +23,4 @@ seata.metrics.registry-type=compact
 seata.registry.namingserver.server-addr=127.0.0.1:8081
 seata.registry.namingserver.namespace=public
 seata.registry.namingserver.heartbeat-period=5000
-seata.server.http.filter.xss.keywords=["<script>", "</script>", "javascript:", 
"vbscript:"]
\ No newline at end of file
+seata.server.http.filter.xss.keywords=["custom1", "custom2"]
\ No newline at end of file


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to