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]