This is an automated email from the ASF dual-hosted git repository.
morningman pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/doris.git
The following commit(s) were added to refs/heads/master by this push:
new 677fc65e0fe [improvement](fe) Move FE web dependencies to supported
OSS releases (#68862)
677fc65e0fe is described below
commit 677fc65e0fe922cd2d576613f4a9fc8ceaefbf66
Author: Mingyu Chen (Rayner) <[email protected]>
AuthorDate: Sun Oct 18 07:55:08 2026 +0100
[improvement](fe) Move FE web dependencies to supported OSS releases
(#68862)
### What problem does this PR solve?
Issue Number: None
Related PR: None
Problem Summary:
FE pins Spring Boot 3.5.16 and Spring Framework 6.2.19 after their OSS
support has ended. For
[CVE-2026-47883](https://spring.io/security/cve-2026-47883/),
[CVE-2026-47889](https://spring.io/security/cve-2026-47889/) and
[CVE-2026-47890](https://spring.io/security/cve-2026-47890/), the
Framework 6.2 fixes are available only in enterprise-supported 6.2.20,
while the OSS fixes are in 7.0.9. Keeping the final OSS 6.2 release
leaves this dependency without an OSS security update path.
This PR upgrades Boot to 4.1.1, Framework to 7.0.9, Spring LDAP to 4.1.1
and Jetty to 12.1.14 with Servlet 6.1 / EE11, retaining Java 17. It
adapts the Boot API packages and replaces the removed optional
trailing-slash matching with request wrapping before MVC routing and
authentication. Boot's Jackson 2 compatibility module preserves existing
HTTP JSON responses; SnakeYAML is aligned with the Boot generation and
the obsolete Tomcat EL override is removed.
It also removes unused direct AWS SDK v1 and cglib dependencies and
excludes the Hadoop YARN client that brings Jetty 9 WebSocket jars into
FE. The Trino connector's existing Jetty 11 HTTP/2 client dependencies
remain pinned and require a separate upstream-client migration.
---
.../authentication/plugin/ldap/LdapClientTest.java | 4 +-
fe/fe-core/pom.xml | 26 +--
.../java/org/apache/doris/httpv2/HttpServer.java | 2 +-
.../httpv2/config/HttpToHttpsJettyConfig.java | 8 +-
.../apache/doris/httpv2/config/WebConfigurer.java | 17 +-
.../config/WebServerFactoryCustomizerConfig.java | 8 +-
.../httpv2/controller/HardwareInfoController.java | 2 +-
.../doris/tls/server/HttpServerTlsProvider.java | 2 +-
.../doris/tls/server/OssHttpServerTlsProvider.java | 4 +-
.../doris/http/HttpServerCompatibilityTest.java | 183 +++++++++++++++++++++
.../mysql/authenticate/ldap/LdapClientTest.java | 4 +-
fe/pom.xml | 82 +++------
12 files changed, 249 insertions(+), 93 deletions(-)
diff --git
a/fe/fe-authentication/fe-authentication-plugins/fe-authentication-plugin-ldap/src/test/java/org/apache/doris/authentication/plugin/ldap/LdapClientTest.java
b/fe/fe-authentication/fe-authentication-plugins/fe-authentication-plugin-ldap/src/test/java/org/apache/doris/authentication/plugin/ldap/LdapClientTest.java
index 7809795062c..45f912747f8 100644
---
a/fe/fe-authentication/fe-authentication-plugins/fe-authentication-plugin-ldap/src/test/java/org/apache/doris/authentication/plugin/ldap/LdapClientTest.java
+++
b/fe/fe-authentication/fe-authentication-plugins/fe-authentication-plugin-ldap/src/test/java/org/apache/doris/authentication/plugin/ldap/LdapClientTest.java
@@ -272,8 +272,8 @@ class LdapClientTest {
String expected = "test\\2a\\28\\29\\5c\\00";
Assertions.assertEquals(expected, LdapEncoder.filterEncode(input));
- // Null input
- Assertions.assertNull(LdapEncoder.filterEncode(null));
+ // Spring LDAP 4 requires a non-null value.
+ Assertions.assertThrows(NullPointerException.class, () ->
LdapEncoder.filterEncode(null));
// Normal username should not be altered
Assertions.assertEquals("zhangsan",
LdapEncoder.filterEncode("zhangsan"));
diff --git a/fe/fe-core/pom.xml b/fe/fe-core/pom.xml
index a488b5d809b..43fc7a869d5 100644
--- a/fe/fe-core/pom.xml
+++ b/fe/fe-core/pom.xml
@@ -194,7 +194,7 @@ under the License.
<exclusions>
<!-- fe-common transitively drags in io.trino:trino-main,
which brings the Jetty
Servlet 5.0 API repackage. Its
jakarta.servlet.http.Cookie lacks getAttributes()
- and would shadow the Servlet 6.1 jakarta.servlet-api that
Jetty 12.0.34 needs,
+ and would shadow the Servlet 6.1 jakarta.servlet-api that
Jetty EE11 needs,
re-introducing the NoSuchMethodError. Keep it off
fe-core's classpath. -->
<exclusion>
<groupId>org.eclipse.jetty.toolchain</groupId>
@@ -451,11 +451,6 @@ under the License.
<groupId>org.apache.commons</groupId>
<artifactId>commons-text</artifactId>
</dependency>
- <!-- https://mvnrepository.com/artifact/cglib/cglib -->
- <dependency>
- <groupId>cglib</groupId>
- <artifactId>cglib</artifactId>
- </dependency>
<!-- https://mvnrepository.com/artifact/commons-cli/commons-cli -->
<dependency>
<groupId>commons-cli</groupId>
@@ -637,10 +632,6 @@ under the License.
<groupId>org.roaringbitmap</groupId>
<artifactId>RoaringBitmap</artifactId>
</dependency>
- <dependency>
- <groupId>com.amazonaws</groupId>
- <artifactId>aws-java-sdk-s3</artifactId>
- </dependency>
<!-- antl4 The version of antlr-runtime in trino parser is need to be
consistent with doris,
when upgrade doris antlr-runtime version, should take care of
trino-parser.-->
<dependency>
@@ -653,10 +644,14 @@ under the License.
<artifactId>fe-sql-parser</artifactId>
<version>${project.version}</version>
</dependency>
- <!--
https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-web
-->
<dependency>
<groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-starter-web</artifactId>
+ <artifactId>spring-boot-starter-webmvc</artifactId>
+ </dependency>
+ <!-- Preserve the Jackson 2 response format used by existing FE HTTP
clients. -->
+ <dependency>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-jackson2</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
@@ -910,11 +905,8 @@ under the License.
<groupId>org.immutables</groupId>
<artifactId>value</artifactId>
</dependency>
- <!-- The FE HTTP server runs on Jetty 12.0.34, which calls
jakarta.servlet.http.Cookie
- #getAttributes() (a Jakarta Servlet 6.1 method) whenever it
writes a Set-Cookie header.
- Declare the servlet API explicitly so fe-core resolves 6.1.0
instead of the transitive
- 6.0.0 from spring-boot; otherwise the server throws
NoSuchMethodError while setting the
- session cookie (surfaced by removing io.trino:trino-main; see
RemoteDorisRestClientTest). -->
+ <!-- Declare the Servlet 6.1 API required by Spring Framework 7 and
Jetty EE11 explicitly;
+ cookie attributes such as SameSite must also resolve against this
API. -->
<dependency>
<groupId>jakarta.servlet</groupId>
<artifactId>jakarta.servlet-api</artifactId>
diff --git a/fe/fe-core/src/main/java/org/apache/doris/httpv2/HttpServer.java
b/fe/fe-core/src/main/java/org/apache/doris/httpv2/HttpServer.java
index 4c61088426e..7324870cc41 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/httpv2/HttpServer.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/httpv2/HttpServer.java
@@ -28,7 +28,7 @@ import org.apache.logging.log4j.Logger;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import
org.springframework.boot.context.properties.EnableConfigurationProperties;
-import org.springframework.boot.web.servlet.ServletComponentScan;
+import
org.springframework.boot.web.server.servlet.context.ServletComponentScan;
import
org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
import org.springframework.context.ConfigurableApplicationContext;
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/httpv2/config/HttpToHttpsJettyConfig.java
b/fe/fe-core/src/main/java/org/apache/doris/httpv2/config/HttpToHttpsJettyConfig.java
index 5952ffe8a04..306c64f8ef8 100644
---
a/fe/fe-core/src/main/java/org/apache/doris/httpv2/config/HttpToHttpsJettyConfig.java
+++
b/fe/fe-core/src/main/java/org/apache/doris/httpv2/config/HttpToHttpsJettyConfig.java
@@ -17,10 +17,10 @@
package org.apache.doris.httpv2.config;
-import org.eclipse.jetty.ee10.servlet.security.ConstraintMapping;
-import org.eclipse.jetty.ee10.servlet.security.ConstraintSecurityHandler;
-import org.eclipse.jetty.ee10.webapp.AbstractConfiguration;
-import org.eclipse.jetty.ee10.webapp.WebAppContext;
+import org.eclipse.jetty.ee11.servlet.security.ConstraintMapping;
+import org.eclipse.jetty.ee11.servlet.security.ConstraintSecurityHandler;
+import org.eclipse.jetty.ee11.webapp.AbstractConfiguration;
+import org.eclipse.jetty.ee11.webapp.WebAppContext;
import org.eclipse.jetty.security.Constraint;
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/httpv2/config/WebConfigurer.java
b/fe/fe-core/src/main/java/org/apache/doris/httpv2/config/WebConfigurer.java
index 255fab71ab6..f7962d91495 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/httpv2/config/WebConfigurer.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/httpv2/config/WebConfigurer.java
@@ -21,14 +21,16 @@ import org.apache.doris.common.Config;
import org.apache.doris.httpv2.interceptor.AuthInterceptor;
import org.apache.doris.httpv2.interceptor.WebUiAvailabilityInterceptor;
-import org.springframework.boot.web.server.ErrorPage;
+import org.springframework.boot.web.error.ErrorPage;
import org.springframework.boot.web.server.WebServerFactoryCustomizer;
-import
org.springframework.boot.web.servlet.server.ConfigurableServletWebServerFactory;
+import
org.springframework.boot.web.server.servlet.ConfigurableServletWebServerFactory;
+import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.Ordered;
import org.springframework.http.HttpStatus;
import org.springframework.util.AntPathMatcher;
+import org.springframework.web.filter.UrlHandlerFilter;
import
org.springframework.web.multipart.support.StandardServletMultipartResolver;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
@@ -64,7 +66,16 @@ public class WebConfigurer implements WebMvcConfigurer {
@Override
public void configurePathMatch(PathMatchConfigurer configurer) {
configurer.setPathMatcher(new AntPathMatcher());
- configurer.setUseTrailingSlashMatch(true);
+ }
+
+ @Bean
+ public FilterRegistrationBean<UrlHandlerFilter> trailingSlashFilter() {
+ // Spring 7 removed optional trailing-slash matching. Wrap requests
before MVC routing
+ // and authentication so existing clients keep their URLs, methods,
bodies and queries.
+ FilterRegistrationBean<UrlHandlerFilter> registration = new
FilterRegistrationBean<>(
+
UrlHandlerFilter.trailingSlashHandler("/**").wrapRequest().build());
+ registration.setOrder(Ordered.HIGHEST_PRECEDENCE + 1);
+ return registration;
}
@Override
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/httpv2/config/WebServerFactoryCustomizerConfig.java
b/fe/fe-core/src/main/java/org/apache/doris/httpv2/config/WebServerFactoryCustomizerConfig.java
index 0de359695fd..9457ed153d8 100644
---
a/fe/fe-core/src/main/java/org/apache/doris/httpv2/config/WebServerFactoryCustomizerConfig.java
+++
b/fe/fe-core/src/main/java/org/apache/doris/httpv2/config/WebServerFactoryCustomizerConfig.java
@@ -22,13 +22,13 @@ import
org.apache.doris.tls.server.HttpServerTlsProviderFactory;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
-import org.eclipse.jetty.ee10.webapp.WebAppContext;
-import
org.eclipse.jetty.ee10.websocket.server.config.JettyWebSocketServletContainerInitializer;
+import org.eclipse.jetty.ee11.webapp.WebAppContext;
+import
org.eclipse.jetty.ee11.websocket.server.config.JettyWebSocketServletContainerInitializer;
import org.eclipse.jetty.server.HttpConfiguration;
import org.eclipse.jetty.server.HttpConnectionFactory;
import org.eclipse.jetty.server.ServerConnector;
-import
org.springframework.boot.web.embedded.jetty.ConfigurableJettyWebServerFactory;
-import
org.springframework.boot.web.embedded.jetty.JettyServletWebServerFactory;
+import org.springframework.boot.jetty.ConfigurableJettyWebServerFactory;
+import org.springframework.boot.jetty.servlet.JettyServletWebServerFactory;
import org.springframework.boot.web.server.WebServerFactoryCustomizer;
import org.springframework.context.annotation.Configuration;
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/httpv2/controller/HardwareInfoController.java
b/fe/fe-core/src/main/java/org/apache/doris/httpv2/controller/HardwareInfoController.java
index 169d3ac8daf..8f2196fc216 100644
---
a/fe/fe-core/src/main/java/org/apache/doris/httpv2/controller/HardwareInfoController.java
+++
b/fe/fe-core/src/main/java/org/apache/doris/httpv2/controller/HardwareInfoController.java
@@ -55,7 +55,7 @@ public class HardwareInfoController {
private static final Logger LOG =
LogManager.getLogger(HardwareInfoController.class);
- @RequestMapping(path = "/hardware_info/fe/", method = RequestMethod.GET)
+ @RequestMapping(path = "/hardware_info/fe", method = RequestMethod.GET)
public Object index() {
Map<String, Map<String, String>> map = new HashMap<>();
appendVersionInfo(map);
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/tls/server/HttpServerTlsProvider.java
b/fe/fe-core/src/main/java/org/apache/doris/tls/server/HttpServerTlsProvider.java
index d42bd16e137..419ce99e229 100644
---
a/fe/fe-core/src/main/java/org/apache/doris/tls/server/HttpServerTlsProvider.java
+++
b/fe/fe-core/src/main/java/org/apache/doris/tls/server/HttpServerTlsProvider.java
@@ -17,7 +17,7 @@
package org.apache.doris.tls.server;
-import
org.springframework.boot.web.embedded.jetty.ConfigurableJettyWebServerFactory;
+import org.springframework.boot.jetty.ConfigurableJettyWebServerFactory;
public interface HttpServerTlsProvider {
void customize(ConfigurableJettyWebServerFactory factory);
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/tls/server/OssHttpServerTlsProvider.java
b/fe/fe-core/src/main/java/org/apache/doris/tls/server/OssHttpServerTlsProvider.java
index 8279b636a3f..64e313558b4 100644
---
a/fe/fe-core/src/main/java/org/apache/doris/tls/server/OssHttpServerTlsProvider.java
+++
b/fe/fe-core/src/main/java/org/apache/doris/tls/server/OssHttpServerTlsProvider.java
@@ -23,8 +23,8 @@ import org.apache.doris.httpv2.config.HttpToHttpsJettyConfig;
import org.eclipse.jetty.server.HttpConfiguration;
import org.eclipse.jetty.server.HttpConnectionFactory;
import org.eclipse.jetty.server.ServerConnector;
-import
org.springframework.boot.web.embedded.jetty.ConfigurableJettyWebServerFactory;
-import
org.springframework.boot.web.embedded.jetty.JettyServletWebServerFactory;
+import org.springframework.boot.jetty.ConfigurableJettyWebServerFactory;
+import org.springframework.boot.jetty.servlet.JettyServletWebServerFactory;
import java.util.Collections;
diff --git
a/fe/fe-core/src/test/java/org/apache/doris/http/HttpServerCompatibilityTest.java
b/fe/fe-core/src/test/java/org/apache/doris/http/HttpServerCompatibilityTest.java
new file mode 100644
index 00000000000..3dd92b2889d
--- /dev/null
+++
b/fe/fe-core/src/test/java/org/apache/doris/http/HttpServerCompatibilityTest.java
@@ -0,0 +1,183 @@
+// 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.doris.http;
+
+import org.apache.doris.common.Config;
+import org.apache.doris.httpv2.config.WebConfigurer;
+import org.apache.doris.httpv2.config.WebServerFactoryCustomizerConfig;
+import org.apache.doris.httpv2.ui.UiApiExceptionHandler;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.google.gson.JsonObject;
+import com.google.gson.JsonParser;
+import jakarta.servlet.http.Cookie;
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletResponse;
+import org.junit.jupiter.api.AfterAll;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.Test;
+import org.springframework.boot.WebApplicationType;
+import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
+import org.springframework.boot.builder.SpringApplicationBuilder;
+import
org.springframework.boot.web.server.servlet.context.ServletWebServerApplicationContext;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Import;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
+import org.springframework.web.bind.annotation.RestControllerAdvice;
+
+import java.net.URI;
+import java.net.http.HttpClient;
+import java.net.http.HttpRequest;
+import java.net.http.HttpResponse;
+import java.time.Duration;
+import java.time.LocalDate;
+import java.util.Locale;
+
+/** Exercises the FE web configuration against the embedded servlet container
and real HTTP requests. */
+public class HttpServerCompatibilityTest {
+ private static final HttpClient CLIENT = HttpClient.newBuilder()
+ .connectTimeout(Duration.ofSeconds(10))
+ .followRedirects(HttpClient.Redirect.NEVER)
+ .build();
+ private static ServletWebServerApplicationContext applicationContext;
+ private static String baseUrl;
+
+ @BeforeAll
+ static void startServer() {
+ Assertions.assertTrue(Config.enable_all_http_auth);
+ Assertions.assertTrue(Config.enable_web_ui);
+ applicationContext = (ServletWebServerApplicationContext) new
SpringApplicationBuilder(TestApplication.class)
+ .web(WebApplicationType.SERVLET)
+ .properties("server.address=127.0.0.1", "server.port=0",
"spring.main.banner-mode=off")
+ .run();
+ baseUrl = "http://127.0.0.1:" +
applicationContext.getWebServer().getPort();
+ }
+
+ @AfterAll
+ static void stopServer() {
+ applicationContext.close();
+ }
+
+ @Test
+ void preservesJsonAndQueryParametersWithTrailingSlash() throws Exception {
+ for (String path : new String[] {"/api/dependency_compatibility",
"/api/dependency_compatibility/"}) {
+ HttpResponse<String> response =
send(HttpRequest.newBuilder(URI.create(baseUrl + path + "?q=hello%20world"))
+ .GET().build());
+ Assertions.assertEquals(200, response.statusCode());
+ JsonObject body =
JsonParser.parseString(response.body()).getAsJsonObject();
+ Assertions.assertEquals("hello world",
body.get("snake_case").getAsString());
+ Assertions.assertEquals("2026-10-10",
body.get("date").getAsString());
+ Assertions.assertFalse(body.has("value"));
+ }
+ }
+
+ @Test
+ void preservesPostMethodAndJsonBodyWithTrailingSlash() throws Exception {
+ for (String path : new String[] {"/api/dependency_compatibility",
"/api/dependency_compatibility/"}) {
+ HttpResponse<String> response =
send(HttpRequest.newBuilder(URI.create(baseUrl + path + "?q=hello%20world"))
+ .header("Content-Type", "application/json")
+
.POST(HttpRequest.BodyPublishers.ofString("{\"snake_case\":\"body\",\"date\":\"2026-10-10\"}"))
+ .build());
+ Assertions.assertEquals(200, response.statusCode());
+ JsonObject body =
JsonParser.parseString(response.body()).getAsJsonObject();
+ Assertions.assertEquals("body:hello world",
body.get("snake_case").getAsString());
+ Assertions.assertEquals("2026-10-10",
body.get("date").getAsString());
+ }
+ }
+
+ @Test
+ void preservesCookieSecurityAttributes() throws Exception {
+ HttpResponse<String> response =
send(HttpRequest.newBuilder(URI.create(baseUrl + "/api/dependency_cookie"))
+ .GET().build());
+ Assertions.assertEquals(200, response.statusCode());
+ String cookie =
response.headers().firstValue("Set-Cookie").orElseThrow().toLowerCase(Locale.ROOT);
+ Assertions.assertTrue(cookie.contains("httponly"));
+ Assertions.assertTrue(cookie.contains("samesite=lax"));
+ }
+
+ @Test
+ void requiresAuthenticationWithAndWithoutTrailingSlash() throws Exception {
+ for (String path : new String[]
{"/rest/v1/ui/dependency_compatibility",
"/rest/v1/ui/dependency_compatibility/"}) {
+ HttpResponse<String> response =
send(HttpRequest.newBuilder(URI.create(baseUrl + path)).GET().build());
+ Assertions.assertEquals(401, response.statusCode());
+
Assertions.assertFalse(response.headers().firstValue("Location").isPresent());
+ }
+ }
+
+ @Test
+ void preservesRootPath() throws Exception {
+ HttpResponse<String> response =
send(HttpRequest.newBuilder(URI.create(baseUrl + "/")).GET().build());
+ Assertions.assertEquals(200, response.statusCode());
+ Assertions.assertEquals("root", response.body());
+ }
+
+ private HttpResponse<String> send(HttpRequest request) throws Exception {
+ return CLIENT.send(request, HttpResponse.BodyHandlers.ofString());
+ }
+
+ @Configuration(proxyBeanMethods = false)
+ @EnableAutoConfiguration
+ @Import({WebConfigurer.class, WebServerFactoryCustomizerConfig.class,
+ CompatibilityExceptionHandler.class,
CompatibilityController.class})
+ public static class TestApplication {
+ }
+
+ @RestControllerAdvice
+ public static class CompatibilityExceptionHandler extends
UiApiExceptionHandler {
+ }
+
+ @RestController
+ public static class CompatibilityController {
+ @GetMapping("/api/dependency_compatibility")
+ public LegacyPayload get(@RequestParam("q") String query) {
+ return new LegacyPayload(query, LocalDate.of(2026, 10, 10));
+ }
+
+ @PostMapping("/api/dependency_compatibility")
+ public LegacyPayload post(@RequestBody LegacyPayload payload,
HttpServletRequest request) {
+ return new LegacyPayload(payload.value() + ":" +
request.getParameter("q"), payload.date());
+ }
+
+ @GetMapping("/api/dependency_cookie")
+ public String cookie(HttpServletResponse response) {
+ Cookie cookie = new Cookie("compatibility_session", "value");
+ cookie.setHttpOnly(true);
+ cookie.setAttribute("SameSite", "Lax");
+ response.addCookie(cookie);
+ return "ok";
+ }
+
+ @GetMapping("/rest/v1/ui/dependency_compatibility")
+ public String protectedEndpoint() {
+ return "authenticated";
+ }
+
+ @GetMapping("/")
+ public String root() {
+ return "root";
+ }
+ }
+
+ public record LegacyPayload(@JsonProperty("snake_case") String value,
LocalDate date) {
+ }
+}
diff --git
a/fe/fe-core/src/test/java/org/apache/doris/mysql/authenticate/ldap/LdapClientTest.java
b/fe/fe-core/src/test/java/org/apache/doris/mysql/authenticate/ldap/LdapClientTest.java
index 72cf5beff6e..f874d6c79e4 100644
---
a/fe/fe-core/src/test/java/org/apache/doris/mysql/authenticate/ldap/LdapClientTest.java
+++
b/fe/fe-core/src/test/java/org/apache/doris/mysql/authenticate/ldap/LdapClientTest.java
@@ -101,8 +101,8 @@ public class LdapClientTest {
String expected = "test\\2a\\28\\29\\5c\\00";
Assertions.assertEquals(expected, LdapEncoder.filterEncode(input));
- // Null input
- Assertions.assertNull(LdapEncoder.filterEncode(null));
+ // Spring LDAP 4 requires a non-null value.
+ Assertions.assertThrows(NullPointerException.class, () ->
LdapEncoder.filterEncode(null));
// Normal username should not be altered
Assertions.assertEquals("zhangsan",
LdapEncoder.filterEncode("zhangsan"));
diff --git a/fe/pom.xml b/fe/pom.xml
index a0f247bfe64..420abce568a 100644
--- a/fe/pom.xml
+++ b/fe/pom.xml
@@ -274,7 +274,6 @@ under the License.
<skip.plugin>false</skip.plugin>
<sonar.organization>apache</sonar.organization>
<sonar.host.url>https://sonarcloud.io</sonar.host.url>
- <cglib.version>2.2</cglib.version>
<commons-cli.version>1.4</commons-cli.version>
<commons-filerupload.version>1.6.0</commons-filerupload.version>
<commons-configuration2.version>2.15.1</commons-configuration2.version>
@@ -294,10 +293,7 @@ under the License.
<jackson.version>2.21.5</jackson.version>
<javassist.version>3.18.2-GA</javassist.version>
<javax.servlet-api.version>3.1.0</javax.servlet-api.version>
- <!-- Jetty 12.0.38 (jetty-ee10-servlet) invokes
jakarta.servlet.http.Cookie#getAttributes(),
- which only exists since Jakarta Servlet 6.1. Pin the API to 6.1.0
so it matches the
- jetty version; otherwise the transitive 6.0.0 from spring-boot
triggers NoSuchMethodError
- when the FE HTTP server writes a Set-Cookie (SameSite) header. -->
+ <!-- Spring Framework 7 and Jetty EE11 require Jakarta Servlet 6.1. -->
<jakarta.servlet-api.version>6.1.0</jakarta.servlet-api.version>
<je.version>18.3.14-doris-SNAPSHOT</je.version>
<commons-io.version>2.18.0</commons-io.version>
@@ -307,7 +303,6 @@ under the License.
<junit.version>5.14.1</junit.version>
<hikaricp.version>6.0.0</hikaricp.version>
<thrift.version>0.24.0</thrift.version>
- <tomcat-embed.version>9.0.104</tomcat-embed.version>
<log4j2.version>2.25.5</log4j2.version>
<log4j-1.2.version>2.25.5</log4j-1.2.version>
<slf4j.version>2.0.17</slf4j.version>
@@ -344,7 +339,7 @@ under the License.
<jetty-servlet.version>11.0.26</jetty-servlet.version>
<jetty-websocket.version>9.4.58.v20250814</jetty-websocket.version>
<okhttp.version>5.3.2</okhttp.version>
- <snakeyaml.version>2.0</snakeyaml.version>
+ <snakeyaml.version>2.6</snakeyaml.version>
<zjsonpatch.version>0.2.3</zjsonpatch.version>
<kafka-clients.version>3.4.0</kafka-clients.version>
<oshi-core.version>6.4.5</oshi-core.version>
@@ -388,7 +383,6 @@ under the License.
(CVE-2026-54399 and CVE-2026-54428). Use their fixed maintenance
releases. -->
<httpclient5.version>5.6.4</httpclient5.version>
<httpcore5.version>5.4.3</httpcore5.version>
- <aws-java-sdk.version>1.12.669</aws-java-sdk.version>
<mariadb-java-client.version>3.0.9</mariadb-java-client.version>
<postgresql.version>42.7.13</postgresql.version>
<hadoop.version>3.4.2</hadoop.version>
@@ -401,12 +395,12 @@ under the License.
<antlr4.version>4.13.1</antlr4.version>
<joda.version>2.8.1</joda.version>
<project.scm.id>github</project.scm.id>
- <!-- Spring Boot 3.5.16 manages fixed Spring LDAP 3.3.8, Spring Data
3.5.13,
- Micrometer 1.15.12, and Logback 1.5.34 releases for their 2026
advisories. -->
- <spring.version>3.5.16</spring.version>
- <!-- Spring Framework 6.2.19 fixes the June 2026 security advisory
set, including
- CVE-2026-41848; keep the explicit framework BOM aligned with that
release. -->
- <spring-framework.version>6.2.19</spring-framework.version>
+ <!-- Boot 3.5 and Framework 6.2 have ended OSS support. Boot 4.1
manages the
+ supported Spring LDAP and Spring Data generations. -->
+ <spring.version>4.1.1</spring.version>
+ <!-- 7.0.9 provides OSS fixes for the August 2026 advisories, including
+ CVE-2026-47883, CVE-2026-47889, and CVE-2026-47890. -->
+ <spring-framework.version>7.0.9</spring-framework.version>
<orc.version>1.8.4</orc.version>
<zookeeper.version>3.9.3</zookeeper.version>
<velocity-engine-core.version>2.4</velocity-engine-core.version>
@@ -420,9 +414,8 @@ under the License.
<woodstox.version>6.5.1</woodstox.version>
<kerby.version>2.0.3</kerby.version>
<jettison.version>1.5.4</jettison.version>
- <!-- Jetty 12.0.34 is affected by CVE-2026-6790, CVE-2026-8384,
- CVE-2026-10050, and CVE-2026-10051; 12.0.38 contains all
published fixes. -->
- <jetty.version>12.0.38</jetty.version>
+ <!-- Spring Framework 7 uses the Servlet 6.1 / Jetty EE11 baseline. -->
+ <jetty.version>12.1.14</jetty.version>
<jetty-http.version>11.0.26</jetty-http.version>
<!-- org.lz4:lz4-java is archived and vulnerable through its final
1.8.x line.
Resolve its official 1.8.1 relocation POM, then manage the
maintained coordinate at
@@ -705,11 +698,10 @@ under the License.
<scope>import</scope>
<type>pom</type>
</dependency>
- <!-- The core Jetty BOM does not manage Jakarta EE 10 artifacts;
import the matching
- EE10 BOM before Spring Boot so the complete Jetty 12 graph
stays on 12.0.38. -->
+ <!-- Align the EE11 servlet modules with the core Jetty BOM before
Spring Boot. -->
<dependency>
- <groupId>org.eclipse.jetty.ee10</groupId>
- <artifactId>jetty-ee10-bom</artifactId>
+ <groupId>org.eclipse.jetty.ee11</groupId>
+ <artifactId>jetty-ee11-bom</artifactId>
<version>${jetty.version}</version>
<scope>import</scope>
<type>pom</type>
@@ -860,13 +852,19 @@ under the License.
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-starter-web</artifactId>
+ <artifactId>spring-boot-starter-webmvc</artifactId>
<version>${spring.version}</version>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</exclusion>
+ <!-- Keep the FE's Jackson 2 HTTP serialization while its
catalog and
+ filesystem dependencies still use Jackson 2. -->
+ <exclusion>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-starter-jackson</artifactId>
+ </exclusion>
<exclusion>
<groupId>validator</groupId>
<artifactId>hibernate-validator</artifactId>
@@ -910,6 +908,11 @@ under the License.
<groupId>org.apache.hadoop</groupId>
<artifactId>hadoop-yarn-api</artifactId>
</exclusion>
+ <!-- Doris does not use YARN; its client brings EOL Jetty
9 WebSocket jars. -->
+ <exclusion>
+ <groupId>org.apache.hadoop</groupId>
+ <artifactId>hadoop-yarn-client</artifactId>
+ </exclusion>
<exclusion>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-reload4j</artifactId>
@@ -1001,18 +1004,6 @@ under the License.
<artifactId>fe-trino-connector-common</artifactId>
<version>${project.version}</version>
</dependency>
- <!-- https://mvnrepository.com/artifact/cglib/cglib -->
- <dependency>
- <groupId>cglib</groupId>
- <artifactId>cglib</artifactId>
- <version>${cglib.version}</version>
- <exclusions>
- <exclusion>
- <artifactId>asm</artifactId>
- <groupId>asm</groupId>
- </exclusion>
- </exclusions>
- </dependency>
<!-- https://mvnrepository.com/artifact/commons-cli/commons-cli -->
<dependency>
<groupId>commons-cli</groupId>
@@ -1849,21 +1840,6 @@ under the License.
<artifactId>httpcore</artifactId>
<version>${httpcore.version}</version>
</dependency>
- <dependency>
- <groupId>com.amazonaws</groupId>
- <artifactId>aws-java-sdk-s3</artifactId>
- <version>${aws-java-sdk.version}</version>
- </dependency>
- <dependency>
- <groupId>com.amazonaws</groupId>
- <artifactId>aws-java-sdk-glue</artifactId>
- <version>${aws-java-sdk.version}</version>
- </dependency>
- <dependency>
- <groupId>com.amazonaws</groupId>
- <artifactId>aws-java-sdk-sts</artifactId>
- <version>${aws-java-sdk.version}</version>
- </dependency>
<dependency>
<groupId>org.mariadb.jdbc</groupId>
<artifactId>mariadb-java-client</artifactId>
@@ -1925,12 +1901,6 @@ under the License.
<artifactId>joda-time</artifactId>
<version>${joda.version}</version>
</dependency>
- <!--tomcat-->
- <dependency>
- <groupId>org.apache.tomcat.embed</groupId>
- <artifactId>tomcat-embed-el</artifactId>
- <version>${tomcat-embed.version}</version>
- </dependency>
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-tcnative-boringssl-static</artifactId>
@@ -2081,7 +2051,7 @@ under the License.
fe-trino-connector-common and fe-connector-trino all
reach it through here).
Its jakarta.servlet.http.Cookie predates Servlet 6.1
and has no
getAttributes(), so whenever it wins classpath order
over
- jakarta:jakarta.servlet-api it shadows the method
Jetty 12.0.34 calls while
+ jakarta:jakarta.servlet-api it shadows the method
Jetty EE11 calls while
writing a Set-Cookie header -> NoSuchMethodError,
which
RestApiExceptionHandler turns into an error payload,
so every cookie-carrying
REST endpoint silently answers with no data
(RemoteDorisRestClientTest
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]