VYPR
Moderate severityNVD Advisory· Published Oct 18, 2024· Updated Nov 29, 2024

CVE-2024-38820: Spring Framework DataBinder Case Sensitive Match Exception

CVE-2024-38820

Description

The fix for CVE-2022-22968 made disallowedFields patterns in DataBinder case insensitive. However, String.toLowerCase() has some Locale dependent exceptions that could potentially result in fields not protected as expected.

AI Insight

LLM-synthesized narrative grounded in this CVE's description and references.

Locale-dependent String.toLowerCase() in Spring DataBinder can bypass disallowedFields protection, allowing unintended field binding.

Root

Cause

CVE-2024-38820 arises from an incomplete fix for CVE-2022-22968, which made disallowedFields patterns in Spring Framework's DataBinder case-insensitive by converting field names to lowercase using String.toLowerCase(). However, this method is locale-dependent; certain locales, such as Turkish, have special case mapping rules (e.g., the letter 'I' maps to 'ı' instead of 'i'). This can cause a mismatch between the lowercased field name and the intended disallowedFields pattern, leaving some fields unprotected [1][2].

Attack

Vector

An attacker can exploit this by sending HTTP requests with property names that, when lowercased under a vulnerable locale, do not match the expected pattern. The attack requires the application to use DataBinder with disallowedFields and the server to run under a locale with non-standard case mappings (e.g., tr-TR). No authentication is required if the binder is exposed on a public endpoint [2].

Impact

Successful exploitation allows an attacker to bind values to fields that were intended to be disallowed, potentially leading to manipulation of internal object properties. This could result in security bypasses, such as overwriting sensitive fields or enabling further injection attacks, depending on the application logic [2].

Mitigation

The Spring Framework team has fixed the issue by consistently using Locale.ROOT when converting field names to lowercase, ensuring locale-independent behavior [1]. The fix is included in Spring Framework 6.2.0-RC2 and later [3]. Users are advised to upgrade to the patched version or apply the corresponding commit [1].

AI Insight generated on May 20, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.

Affected packages

Versions sourced from the GitHub Security Advisory.

PackageAffected versionsPatched versions
org.springframework:spring-contextMaven
>= 6.1.0, < 6.1.146.1.14
org.springframework:spring-webMaven
>= 6.1.0, < 6.1.146.1.14
org.springframework:spring-webMaven
>= 6.0.0, <= 6.0.24
org.springframework:spring-contextMaven
>= 6.0.0, <= 6.0.24
org.springframework:spring-contextMaven
<= 5.3.40
org.springframework:spring-webMaven
<= 5.3.40

Affected products

27

Patches

2
23656aebc6c7

Use Locale.ROOT consistently for toLower/toUpperCase

43 files changed · +106 82
  • framework-docs/src/main/java/org/springframework/docs/integration/observability/config/conventions/CustomServerRequestObservationConvention.java+4 2 modified
    @@ -1,5 +1,5 @@
     /*
    - * Copyright 2002-2023 the original author or authors.
    + * Copyright 2002-2024 the original author or authors.
      *
      * Licensed under the Apache License, Version 2.0 (the "License");
      * you may not use this file except in compliance with the License.
    @@ -16,6 +16,8 @@
     
     package org.springframework.docs.integration.observability.config.conventions;
     
    +import java.util.Locale;
    +
     import io.micrometer.common.KeyValue;
     import io.micrometer.common.KeyValues;
     
    @@ -34,7 +36,7 @@ public String getName() {
     	@Override
     	public String getContextualName(ServerRequestObservationContext context) {
     		// will be used for the trace name
    -		return "http " + context.getCarrier().getMethod().toLowerCase();
    +		return "http " + context.getCarrier().getMethod().toLowerCase(Locale.ROOT);
     	}
     
     	@Override
    
  • spring-context/src/main/java/org/springframework/validation/DataBinder.java+4 2 modified
    @@ -27,6 +27,7 @@
     import java.util.HashMap;
     import java.util.HashSet;
     import java.util.List;
    +import java.util.Locale;
     import java.util.Map;
     import java.util.Optional;
     import java.util.Set;
    @@ -568,7 +569,8 @@ public void setDisallowedFields(@Nullable String... disallowedFields) {
     		else {
     			String[] fieldPatterns = new String[disallowedFields.length];
     			for (int i = 0; i < fieldPatterns.length; i++) {
    -				fieldPatterns[i] = PropertyAccessorUtils.canonicalPropertyName(disallowedFields[i]).toLowerCase();
    +				String field = PropertyAccessorUtils.canonicalPropertyName(disallowedFields[i]);
    +				fieldPatterns[i] = field.toLowerCase(Locale.ROOT);
     			}
     			this.disallowedFields = fieldPatterns;
     		}
    @@ -1157,7 +1159,7 @@ protected boolean isAllowed(String field) {
     		String[] allowed = getAllowedFields();
     		String[] disallowed = getDisallowedFields();
     		return ((ObjectUtils.isEmpty(allowed) || PatternMatchUtils.simpleMatch(allowed, field)) &&
    -				(ObjectUtils.isEmpty(disallowed) || !PatternMatchUtils.simpleMatch(disallowed, field.toLowerCase())));
    +				(ObjectUtils.isEmpty(disallowed) || !PatternMatchUtils.simpleMatch(disallowed, field.toLowerCase(Locale.ROOT))));
     	}
     
     	/**
    
  • spring-core/src/main/java/org/springframework/util/MimeType.java+4 4 modified
    @@ -1,5 +1,5 @@
     /*
    - * Copyright 2002-2023 the original author or authors.
    + * Copyright 2002-2024 the original author or authors.
      *
      * Licensed under the Apache License, Version 2.0 (the "License");
      * you may not use this file except in compliance with the License.
    @@ -181,10 +181,10 @@ public MimeType(String type, String subtype, @Nullable Map<String, String> param
     		Assert.hasLength(subtype, "'subtype' must not be empty");
     		checkToken(type);
     		checkToken(subtype);
    -		this.type = type.toLowerCase(Locale.ENGLISH);
    -		this.subtype = subtype.toLowerCase(Locale.ENGLISH);
    +		this.type = type.toLowerCase(Locale.ROOT);
    +		this.subtype = subtype.toLowerCase(Locale.ROOT);
     		if (!CollectionUtils.isEmpty(parameters)) {
    -			Map<String, String> map = new LinkedCaseInsensitiveMap<>(parameters.size(), Locale.ENGLISH);
    +			Map<String, String> map = new LinkedCaseInsensitiveMap<>(parameters.size(), Locale.ROOT);
     			parameters.forEach((parameter, value) -> {
     				checkParameters(parameter, value);
     				map.put(parameter, value);
    
  • spring-test/src/main/java/org/springframework/mock/web/MockHttpServletRequest.java+3 2 modified
    @@ -409,7 +409,8 @@ public void setCharacterEncoding(@Nullable String characterEncoding) {
     	private void updateContentTypeHeader() {
     		if (StringUtils.hasLength(this.contentType)) {
     			String value = this.contentType;
    -			if (StringUtils.hasLength(this.characterEncoding) && !this.contentType.toLowerCase().contains(CHARSET_PREFIX)) {
    +			if (StringUtils.hasLength(this.characterEncoding) &&
    +					!this.contentType.toLowerCase(Locale.ROOT).contains(CHARSET_PREFIX)) {
     				value += ';' + CHARSET_PREFIX + this.characterEncoding;
     			}
     			doAddHeaderValue(HttpHeaders.CONTENT_TYPE, value, true);
    @@ -487,7 +488,7 @@ public void setContentType(@Nullable String contentType) {
     			}
     			catch (IllegalArgumentException ex) {
     				// Try to get charset value anyway
    -				contentType = contentType.toLowerCase();
    +				contentType = contentType.toLowerCase(Locale.ROOT);
     				int charsetIndex = contentType.indexOf(CHARSET_PREFIX);
     				if (charsetIndex != -1) {
     					this.characterEncoding = contentType.substring(charsetIndex + CHARSET_PREFIX.length());
    
  • spring-test/src/main/java/org/springframework/mock/web/MockHttpServletResponse.java+3 3 modified
    @@ -223,7 +223,7 @@ private void setExplicitCharacterEncoding(@Nullable String characterEncoding) {
     				}
     				catch (Exception ignored) {
     					String value = this.contentType;
    -					int charsetIndex = value.toLowerCase().indexOf(CHARSET_PREFIX);
    +					int charsetIndex = value.toLowerCase(Locale.ROOT).indexOf(CHARSET_PREFIX);
     					if (charsetIndex != -1) {
     						value = value.substring(0, charsetIndex).trim();
     						if (value.endsWith(";")) {
    @@ -243,7 +243,7 @@ private void setExplicitCharacterEncoding(@Nullable String characterEncoding) {
     	private void updateContentTypePropertyAndHeader() {
     		if (this.contentType != null) {
     			String value = this.contentType;
    -			if (this.characterEncodingSet && !value.toLowerCase().contains(CHARSET_PREFIX)) {
    +			if (this.characterEncodingSet && !value.toLowerCase(Locale.ROOT).contains(CHARSET_PREFIX)) {
     				value += ';' + CHARSET_PREFIX + getCharacterEncoding();
     				this.contentType = value;
     			}
    @@ -351,7 +351,7 @@ public void setContentType(@Nullable String contentType) {
     			}
     			catch (Exception ex) {
     				// Try to get charset value anyway
    -				int charsetIndex = contentType.toLowerCase().indexOf(CHARSET_PREFIX);
    +				int charsetIndex = contentType.toLowerCase(Locale.ROOT).indexOf(CHARSET_PREFIX);
     				if (charsetIndex != -1) {
     					setExplicitCharacterEncoding(contentType.substring(charsetIndex + CHARSET_PREFIX.length()));
     				}
    
  • spring-webflux/src/main/java/org/springframework/web/reactive/accept/ParameterContentTypeResolver.java+2 2 modified
    @@ -1,5 +1,5 @@
     /*
    - * Copyright 2002-2017 the original author or authors.
    + * Copyright 2002-2024 the original author or authors.
      *
      * Licensed under the Apache License, Version 2.0 (the "License");
      * you may not use this file except in compliance with the License.
    @@ -51,7 +51,7 @@ public ParameterContentTypeResolver(Map<String, MediaType> mediaTypes) {
     	}
     
     	private static String formatKey(String key) {
    -		return key.toLowerCase(Locale.ENGLISH);
    +		return key.toLowerCase(Locale.ROOT);
     	}
     
     
    
  • spring-webflux/src/main/java/org/springframework/web/reactive/function/client/DefaultClientRequestObservationConvention.java+2 1 modified
    @@ -17,6 +17,7 @@
     package org.springframework.web.reactive.function.client;
     
     import java.io.IOException;
    +import java.util.Locale;
     import java.util.regex.Pattern;
     
     import io.micrometer.common.KeyValue;
    @@ -92,7 +93,7 @@ public String getName() {
     	@Nullable
     	public String getContextualName(ClientRequestObservationContext context) {
     		ClientRequest request = context.getRequest();
    -		return (request != null ? "http " + request.method().name().toLowerCase() : null);
    +		return (request != null ? "http " + request.method().name().toLowerCase(Locale.ROOT) : null);
     	}
     
     	@Override
    
  • spring-webflux/src/main/java/org/springframework/web/reactive/resource/CachingResourceResolver.java+3 2 modified
    @@ -1,5 +1,5 @@
     /*
    - * Copyright 2002-2019 the original author or authors.
    + * Copyright 2002-2024 the original author or authors.
      *
      * Licensed under the Apache License, Version 2.0 (the "License");
      * you may not use this file except in compliance with the License.
    @@ -20,6 +20,7 @@
     import java.util.Arrays;
     import java.util.Collections;
     import java.util.List;
    +import java.util.Locale;
     import java.util.stream.Collectors;
     
     import reactor.core.publisher.Mono;
    @@ -140,7 +141,7 @@ private String getContentCodingKey(ServerWebExchange exchange) {
     		return Arrays.stream(StringUtils.tokenizeToStringArray(header, ","))
     				.map(token -> {
     					int index = token.indexOf(';');
    -					return (index >= 0 ? token.substring(0, index) : token).trim().toLowerCase();
    +					return (index >= 0 ? token.substring(0, index) : token).trim().toLowerCase(Locale.ROOT);
     				})
     				.filter(this.contentCodings::contains)
     				.sorted()
    
  • spring-webflux/src/main/java/org/springframework/web/reactive/resource/EncodedResourceResolver.java+3 2 modified
    @@ -1,5 +1,5 @@
     /*
    - * Copyright 2002-2023 the original author or authors.
    + * Copyright 2002-2024 the original author or authors.
      *
      * Licensed under the Apache License, Version 2.0 (the "License");
      * you may not use this file except in compliance with the License.
    @@ -28,6 +28,7 @@
     import java.util.Collections;
     import java.util.LinkedHashMap;
     import java.util.List;
    +import java.util.Locale;
     import java.util.Map;
     
     import reactor.core.publisher.Mono;
    @@ -169,7 +170,7 @@ protected Mono<Resource> resolveResourceInternal(@Nullable ServerWebExchange exc
     	private String getAcceptEncoding(ServerWebExchange exchange) {
     		ServerHttpRequest request = exchange.getRequest();
     		String header = request.getHeaders().getFirst(HttpHeaders.ACCEPT_ENCODING);
    -		return (header != null ? header.toLowerCase() : null);
    +		return (header != null ? header.toLowerCase(Locale.ROOT) : null);
     	}
     
     	private String getExtension(String coding) {
    
  • spring-webflux/src/main/java/org/springframework/web/reactive/resource/ResourceWebHandler.java+3 3 modified
    @@ -1,5 +1,5 @@
     /*
    - * Copyright 2002-2023 the original author or authors.
    + * Copyright 2002-2024 the original author or authors.
      *
      * Licensed under the Apache License, Version 2.0 (the "License");
      * you may not use this file except in compliance with the License.
    @@ -339,7 +339,7 @@ public void setMediaTypes(Map<String, MediaType> mediaTypes) {
     			this.mediaTypes = new HashMap<>(mediaTypes.size());
     		}
     		mediaTypes.forEach((ext, type) ->
    -				this.mediaTypes.put(ext.toLowerCase(Locale.ENGLISH), type));
    +				this.mediaTypes.put(ext.toLowerCase(Locale.ROOT), type));
     	}
     
     	/**
    @@ -664,7 +664,7 @@ private MediaType getMediaType(Resource resource) {
     		if (!CollectionUtils.isEmpty(this.mediaTypes)) {
     			String ext = StringUtils.getFilenameExtension(filename);
     			if (ext != null) {
    -				mediaType = this.mediaTypes.get(ext.toLowerCase(Locale.ENGLISH));
    +				mediaType = this.mediaTypes.get(ext.toLowerCase(Locale.ROOT));
     			}
     		}
     		if (mediaType == null) {
    
  • spring-webflux/src/main/java/org/springframework/web/reactive/result/condition/AbstractNameValueExpression.java+4 2 modified
    @@ -1,5 +1,5 @@
     /*
    - * Copyright 2002-2018 the original author or authors.
    + * Copyright 2002-2024 the original author or authors.
      *
      * Licensed under the Apache License, Version 2.0 (the "License");
      * you may not use this file except in compliance with the License.
    @@ -16,6 +16,8 @@
     
     package org.springframework.web.reactive.result.condition;
     
    +import java.util.Locale;
    +
     import org.springframework.lang.Nullable;
     import org.springframework.util.ObjectUtils;
     import org.springframework.web.server.ServerWebExchange;
    @@ -106,7 +108,7 @@ public boolean equals(@Nullable Object other) {
     
     	@Override
     	public int hashCode() {
    -		int result = (isCaseSensitiveName() ? this.name : this.name.toLowerCase()).hashCode();
    +		int result = (isCaseSensitiveName() ? this.name : this.name.toLowerCase(Locale.ROOT)).hashCode();
     		result = 31 * result + ObjectUtils.nullSafeHashCode(this.value);
     		result = 31 * result + (this.isNegated ? 1 : 0);
     		return result;
    
  • spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/condition/AbstractNameValueExpression.java+4 2 modified
    @@ -1,5 +1,5 @@
     /*
    - * Copyright 2002-2018 the original author or authors.
    + * Copyright 2002-2024 the original author or authors.
      *
      * Licensed under the Apache License, Version 2.0 (the "License");
      * you may not use this file except in compliance with the License.
    @@ -16,6 +16,8 @@
     
     package org.springframework.web.servlet.mvc.condition;
     
    +import java.util.Locale;
    +
     import jakarta.servlet.http.HttpServletRequest;
     
     import org.springframework.lang.Nullable;
    @@ -108,7 +110,7 @@ public boolean equals(@Nullable Object other) {
     
     	@Override
     	public int hashCode() {
    -		int result = (isCaseSensitiveName() ? this.name.hashCode() : this.name.toLowerCase().hashCode());
    +		int result = (isCaseSensitiveName() ? this.name.hashCode() : this.name.toLowerCase(Locale.ROOT).hashCode());
     		result = 31 * result + (this.value != null ? this.value.hashCode() : 0);
     		result = 31 * result + (this.isNegated ? 1 : 0);
     		return result;
    
  • spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/AbstractMessageConverterMethodProcessor.java+2 2 modified
    @@ -1,5 +1,5 @@
     /*
    - * Copyright 2002-2023 the original author or authors.
    + * Copyright 2002-2024 the original author or authors.
      *
      * Licensed under the Apache License, Version 2.0 (the "License");
      * you may not use this file except in compliance with the License.
    @@ -480,7 +480,7 @@ private boolean safeExtension(HttpServletRequest request, @Nullable String exten
     		if (!StringUtils.hasText(extension)) {
     			return true;
     		}
    -		extension = extension.toLowerCase(Locale.ENGLISH);
    +		extension = extension.toLowerCase(Locale.ROOT);
     		if (this.safeExtensions.contains(extension)) {
     			return true;
     		}
    
  • spring-webmvc/src/main/java/org/springframework/web/servlet/resource/CachingResourceResolver.java+3 2 modified
    @@ -1,5 +1,5 @@
     /*
    - * Copyright 2002-2023 the original author or authors.
    + * Copyright 2002-2024 the original author or authors.
      *
      * Licensed under the Apache License, Version 2.0 (the "License");
      * you may not use this file except in compliance with the License.
    @@ -20,6 +20,7 @@
     import java.util.Arrays;
     import java.util.Collections;
     import java.util.List;
    +import java.util.Locale;
     import java.util.stream.Collectors;
     
     import jakarta.servlet.http.HttpServletRequest;
    @@ -147,7 +148,7 @@ private String getContentCodingKey(HttpServletRequest request) {
     		return Arrays.stream(StringUtils.tokenizeToStringArray(header, ","))
     				.map(token -> {
     					int index = token.indexOf(';');
    -					return (index >= 0 ? token.substring(0, index) : token).trim().toLowerCase();
    +					return (index >= 0 ? token.substring(0, index) : token).trim().toLowerCase(Locale.ROOT);
     				})
     				.filter(this.contentCodings::contains)
     				.sorted()
    
  • spring-webmvc/src/main/java/org/springframework/web/servlet/resource/EncodedResourceResolver.java+3 2 modified
    @@ -1,5 +1,5 @@
     /*
    - * Copyright 2002-2023 the original author or authors.
    + * Copyright 2002-2024 the original author or authors.
      *
      * Licensed under the Apache License, Version 2.0 (the "License");
      * you may not use this file except in compliance with the License.
    @@ -28,6 +28,7 @@
     import java.util.Collections;
     import java.util.LinkedHashMap;
     import java.util.List;
    +import java.util.Locale;
     import java.util.Map;
     
     import jakarta.servlet.http.HttpServletRequest;
    @@ -166,7 +167,7 @@ protected Resource resolveResourceInternal(@Nullable HttpServletRequest request,
     	@Nullable
     	private String getAcceptEncoding(HttpServletRequest request) {
     		String header = request.getHeader(HttpHeaders.ACCEPT_ENCODING);
    -		return (header != null ? header.toLowerCase() : null);
    +		return (header != null ? header.toLowerCase(Locale.ROOT) : null);
     	}
     
     	private String getExtension(String coding) {
    
  • spring-webmvc/src/main/java/org/springframework/web/servlet/resource/ResourceHttpRequestHandler.java+3 3 modified
    @@ -1,5 +1,5 @@
     /*
    - * Copyright 2002-2023 the original author or authors.
    + * Copyright 2002-2024 the original author or authors.
      *
      * Licensed under the Apache License, Version 2.0 (the "License");
      * you may not use this file except in compliance with the License.
    @@ -319,7 +319,7 @@ public ContentNegotiationManager getContentNegotiationManager() {
     	 */
     	public void setMediaTypes(Map<String, MediaType> mediaTypes) {
     		mediaTypes.forEach((ext, mediaType) ->
    -				this.mediaTypes.put(ext.toLowerCase(Locale.ENGLISH), mediaType));
    +				this.mediaTypes.put(ext.toLowerCase(Locale.ROOT), mediaType));
     	}
     
     	/**
    @@ -843,7 +843,7 @@ protected MediaType getMediaType(HttpServletRequest request, Resource resource)
     			String filename = resource.getFilename();
     			String ext = StringUtils.getFilenameExtension(filename);
     			if (ext != null) {
    -				mediaType = this.mediaTypes.get(ext.toLowerCase(Locale.ENGLISH));
    +				mediaType = this.mediaTypes.get(ext.toLowerCase(Locale.ROOT));
     			}
     			if (mediaType == null) {
     				List<MediaType> mediaTypes = MediaTypeFactory.getMediaTypes(filename);
    
  • spring-webmvc/src/main/java/org/springframework/web/servlet/view/xslt/XsltView.java+3 2 modified
    @@ -1,5 +1,5 @@
     /*
    - * Copyright 2002-2021 the original author or authors.
    + * Copyright 2002-2024 the original author or authors.
      *
      * Licensed under the Apache License, Version 2.0 (the "License");
      * you may not use this file except in compliance with the License.
    @@ -20,6 +20,7 @@
     import java.io.InputStream;
     import java.io.Reader;
     import java.util.Enumeration;
    +import java.util.Locale;
     import java.util.Map;
     import java.util.Properties;
     
    @@ -414,7 +415,7 @@ protected void configureResponse(Map<String, Object> model, HttpServletResponse
     		}
     		if (StringUtils.hasText(encoding)) {
     			// Only apply encoding if content type is specified but does not contain charset clause already.
    -			if (contentType != null && !contentType.toLowerCase().contains(WebUtils.CONTENT_TYPE_CHARSET_PREFIX)) {
    +			if (contentType != null && !contentType.toLowerCase(Locale.ROOT).contains(WebUtils.CONTENT_TYPE_CHARSET_PREFIX)) {
     				contentType = contentType + WebUtils.CONTENT_TYPE_CHARSET_PREFIX + encoding;
     			}
     		}
    
  • spring-websocket/src/main/java/org/springframework/web/socket/adapter/standard/StandardToWebSocketExtensionAdapter.java+2 2 modified
    @@ -1,5 +1,5 @@
     /*
    - * Copyright 2002-2022 the original author or authors.
    + * Copyright 2002-2024 the original author or authors.
      *
      * Licensed under the Apache License, Version 2.0 (the "License");
      * you may not use this file except in compliance with the License.
    @@ -42,7 +42,7 @@ public StandardToWebSocketExtensionAdapter(Extension extension) {
     
     	private static Map<String, String> initParameters(Extension extension) {
     		List<Extension.Parameter> parameters = extension.getParameters();
    -		Map<String, String> result = new LinkedCaseInsensitiveMap<>(parameters.size(), Locale.ENGLISH);
    +		Map<String, String> result = new LinkedCaseInsensitiveMap<>(parameters.size(), Locale.ROOT);
     		for (Extension.Parameter parameter : parameters) {
     			result.put(parameter.getName(), parameter.getValue());
     		}
    
  • spring-websocket/src/main/java/org/springframework/web/socket/client/standard/StandardWebSocketClient.java+2 2 modified
    @@ -1,5 +1,5 @@
     /*
    - * Copyright 2002-2023 the original author or authors.
    + * Copyright 2002-2024 the original author or authors.
      *
      * Licensed under the Apache License, Version 2.0 (the "License");
      * you may not use this file except in compliance with the License.
    @@ -203,7 +203,7 @@ private static InetAddress getLocalHost() {
     
     	private static int getPort(URI uri) {
     		if (uri.getPort() == -1) {
    -			String scheme = uri.getScheme().toLowerCase(Locale.ENGLISH);
    +			String scheme = uri.getScheme().toLowerCase(Locale.ROOT);
     			return ("wss".equals(scheme) ? 443 : 80);
     		}
     		return uri.getPort();
    
  • spring-websocket/src/main/java/org/springframework/web/socket/WebSocketExtension.java+2 2 modified
    @@ -1,5 +1,5 @@
     /*
    - * Copyright 2002-2022 the original author or authors.
    + * Copyright 2002-2024 the original author or authors.
      *
      * Licensed under the Apache License, Version 2.0 (the "License");
      * you may not use this file except in compliance with the License.
    @@ -72,7 +72,7 @@ public WebSocketExtension(String name, @Nullable Map<String, String> parameters)
     		Assert.hasLength(name, "Extension name must not be empty");
     		this.name = name;
     		if (!CollectionUtils.isEmpty(parameters)) {
    -			Map<String, String> map = new LinkedCaseInsensitiveMap<>(parameters.size(), Locale.ENGLISH);
    +			Map<String, String> map = new LinkedCaseInsensitiveMap<>(parameters.size(), Locale.ROOT);
     			map.putAll(parameters);
     			this.parameters = Collections.unmodifiableMap(map);
     		}
    
  • spring-web/src/main/java/org/springframework/http/client/JdkClientHttpRequest.java+2 1 modified
    @@ -26,6 +26,7 @@
     import java.nio.ByteBuffer;
     import java.time.Duration;
     import java.util.Collections;
    +import java.util.Locale;
     import java.util.Set;
     import java.util.TreeSet;
     import java.util.concurrent.ExecutionException;
    @@ -139,7 +140,7 @@ private HttpRequest buildRequest(HttpHeaders headers, @Nullable Body body) {
     		}
     
     		headers.forEach((headerName, headerValues) -> {
    -			if (!DISALLOWED_HEADERS.contains(headerName.toLowerCase())) {
    +			if (!DISALLOWED_HEADERS.contains(headerName.toLowerCase(Locale.ROOT))) {
     				for (String headerValue : headerValues) {
     					builder.header(headerName, headerValue);
     				}
    
  • spring-web/src/main/java/org/springframework/http/client/JdkClientHttpResponse.java+1 1 modified
    @@ -57,7 +57,7 @@ public JdkClientHttpResponse(HttpResponse<InputStream> response) {
     
     	private static HttpHeaders adaptHeaders(HttpResponse<?> response) {
     		Map<String, List<String>> rawHeaders = response.headers().map();
    -		Map<String, List<String>> map = new LinkedCaseInsensitiveMap<>(rawHeaders.size(), Locale.ENGLISH);
    +		Map<String, List<String>> map = new LinkedCaseInsensitiveMap<>(rawHeaders.size(), Locale.ROOT);
     		MultiValueMap<String, String> multiValueMap = CollectionUtils.toMultiValueMap(map);
     		multiValueMap.putAll(rawHeaders);
     		return HttpHeaders.readOnlyHttpHeaders(multiValueMap);
    
  • spring-web/src/main/java/org/springframework/http/client/observation/DefaultClientRequestObservationConvention.java+2 1 modified
    @@ -17,6 +17,7 @@
     package org.springframework.http.client.observation;
     
     import java.io.IOException;
    +import java.util.Locale;
     import java.util.regex.Pattern;
     
     import io.micrometer.common.KeyValue;
    @@ -89,7 +90,7 @@ public String getName() {
     	@Nullable
     	public String getContextualName(ClientRequestObservationContext context) {
     		ClientHttpRequest request = context.getCarrier();
    -		return (request != null ? "http " + request.getMethod().name().toLowerCase() : null);
    +		return (request != null ? "http " + request.getMethod().name().toLowerCase(Locale.ROOT) : null);
     	}
     
     	@Override
    
  • spring-web/src/main/java/org/springframework/http/client/reactive/JdkClientHttpResponse.java+1 1 modified
    @@ -68,7 +68,7 @@ public JdkClientHttpResponse(HttpResponse<Flow.Publisher<List<ByteBuffer>>> resp
     
     	private static HttpHeaders adaptHeaders(HttpResponse<Flow.Publisher<List<ByteBuffer>>> response) {
     		Map<String, List<String>> rawHeaders = response.headers().map();
    -		Map<String, List<String>> map = new LinkedCaseInsensitiveMap<>(rawHeaders.size(), Locale.ENGLISH);
    +		Map<String, List<String>> map = new LinkedCaseInsensitiveMap<>(rawHeaders.size(), Locale.ROOT);
     		MultiValueMap<String, String> multiValueMap = CollectionUtils.toMultiValueMap(map);
     		multiValueMap.putAll(rawHeaders);
     		return HttpHeaders.readOnlyHttpHeaders(multiValueMap);
    
  • spring-web/src/main/java/org/springframework/http/HttpHeaders.java+3 3 modified
    @@ -392,7 +392,7 @@ public class HttpHeaders implements MultiValueMap<String, String>, Serializable
     	 */
     	public static final HttpHeaders EMPTY = new ReadOnlyHttpHeaders(new LinkedMultiValueMap<>());
     
    -	private static final DecimalFormatSymbols DECIMAL_FORMAT_SYMBOLS = new DecimalFormatSymbols(Locale.ENGLISH);
    +	private static final DecimalFormatSymbols DECIMAL_FORMAT_SYMBOLS = new DecimalFormatSymbols(Locale.ROOT);
     
     	private static final ZoneId GMT = ZoneId.of("GMT");
     
    @@ -422,7 +422,7 @@ public class HttpHeaders implements MultiValueMap<String, String>, Serializable
     	 * <p>This is the common constructor, using a case-insensitive map structure.
     	 */
     	public HttpHeaders() {
    -		this(CollectionUtils.toMultiValueMap(new LinkedCaseInsensitiveMap<>(8, Locale.ENGLISH)));
    +		this(CollectionUtils.toMultiValueMap(new LinkedCaseInsensitiveMap<>(8, Locale.ROOT)));
     	}
     
     	/**
    @@ -697,7 +697,7 @@ public HttpMethod getAccessControlRequestMethod() {
     	public void setAcceptCharset(List<Charset> acceptableCharsets) {
     		StringJoiner joiner = new StringJoiner(", ");
     		for (Charset charset : acceptableCharsets) {
    -			joiner.add(charset.name().toLowerCase(Locale.ENGLISH));
    +			joiner.add(charset.name().toLowerCase(Locale.ROOT));
     		}
     		set(ACCEPT_CHARSET, joiner.toString());
     	}
    
  • spring-web/src/main/java/org/springframework/http/MediaTypeFactory.java+3 3 modified
    @@ -1,5 +1,5 @@
     /*
    - * Copyright 2002-2021 the original author or authors.
    + * Copyright 2002-2024 the original author or authors.
      *
      * Licensed under the Apache License, Version 2.0 (the "License");
      * you may not use this file except in compliance with the License.
    @@ -77,7 +77,7 @@ private static MultiValueMap<String, MediaType> parseMimeTypes() {
     				String[] tokens = StringUtils.tokenizeToStringArray(line, " \t\n\r\f");
     				MediaType mediaType = MediaType.parseMediaType(tokens[0]);
     				for (int i = 1; i < tokens.length; i++) {
    -					String fileExtension = tokens[i].toLowerCase(Locale.ENGLISH);
    +					String fileExtension = tokens[i].toLowerCase(Locale.ROOT);
     					result.add(fileExtension, mediaType);
     				}
     			}
    @@ -117,7 +117,7 @@ public static List<MediaType> getMediaTypes(@Nullable String filename) {
     		List<MediaType> mediaTypes = null;
     		String ext = StringUtils.getFilenameExtension(filename);
     		if (ext != null) {
    -			mediaTypes = fileExtensionToMediaTypes.get(ext.toLowerCase(Locale.ENGLISH));
    +			mediaTypes = fileExtensionToMediaTypes.get(ext.toLowerCase(Locale.ROOT));
     		}
     		return (mediaTypes != null ? mediaTypes : Collections.emptyList());
     	}
    
  • spring-web/src/main/java/org/springframework/http/server/observation/DefaultServerRequestObservationConvention.java+3 2 modified
    @@ -1,5 +1,5 @@
     /*
    - * Copyright 2002-2023 the original author or authors.
    + * Copyright 2002-2024 the original author or authors.
      *
      * Licensed under the Apache License, Version 2.0 (the "License");
      * you may not use this file except in compliance with the License.
    @@ -16,6 +16,7 @@
     
     package org.springframework.http.server.observation;
     
    +import java.util.Locale;
     import java.util.Set;
     import java.util.stream.Collectors;
     import java.util.stream.Stream;
    @@ -89,7 +90,7 @@ public String getName() {
     
     	@Override
     	public String getContextualName(ServerRequestObservationContext context) {
    -		String httpMethod = context.getCarrier().getMethod().toLowerCase();
    +		String httpMethod = context.getCarrier().getMethod().toLowerCase(Locale.ROOT);
     		if (context.getPathPattern() != null) {
     			return "http " + httpMethod + " " + context.getPathPattern();
     		}
    
  • spring-web/src/main/java/org/springframework/http/server/reactive/observation/DefaultServerRequestObservationConvention.java+3 2 modified
    @@ -1,5 +1,5 @@
     /*
    - * Copyright 2002-2023 the original author or authors.
    + * Copyright 2002-2024 the original author or authors.
      *
      * Licensed under the Apache License, Version 2.0 (the "License");
      * you may not use this file except in compliance with the License.
    @@ -16,6 +16,7 @@
     
     package org.springframework.http.server.reactive.observation;
     
    +import java.util.Locale;
     import java.util.Set;
     
     import io.micrometer.common.KeyValue;
    @@ -87,7 +88,7 @@ public String getName() {
     
     	@Override
     	public String getContextualName(ServerRequestObservationContext context) {
    -		String httpMethod = context.getCarrier().getMethod().name().toLowerCase();
    +		String httpMethod = context.getCarrier().getMethod().name().toLowerCase(Locale.ROOT);
     		if (context.getPathPattern() != null) {
     			return "http " + httpMethod + " " + context.getPathPattern();
     		}
    
  • spring-web/src/main/java/org/springframework/http/server/reactive/ServletServerHttpRequest.java+2 2 modified
    @@ -1,5 +1,5 @@
     /*
    - * Copyright 2002-2023 the original author or authors.
    + * Copyright 2002-2024 the original author or authors.
      *
      * Licensed under the Apache License, Version 2.0 (the "License");
      * you may not use this file except in compliance with the License.
    @@ -111,7 +111,7 @@ public ServletServerHttpRequest(MultiValueMap<String, String> headers, HttpServl
     
     	private static MultiValueMap<String, String> createDefaultHttpHeaders(HttpServletRequest request) {
     		MultiValueMap<String, String> headers =
    -				CollectionUtils.toMultiValueMap(new LinkedCaseInsensitiveMap<>(8, Locale.ENGLISH));
    +				CollectionUtils.toMultiValueMap(new LinkedCaseInsensitiveMap<>(8, Locale.ROOT));
     		for (Enumeration<?> names = request.getHeaderNames(); names.hasMoreElements(); ) {
     			String name = (String) names.nextElement();
     			for (Enumeration<?> values = request.getHeaders(name); values.hasMoreElements(); ) {
    
  • spring-web/src/main/java/org/springframework/web/accept/ContentNegotiationManagerFactoryBean.java+2 2 modified
    @@ -1,5 +1,5 @@
     /*
    - * Copyright 2002-2021 the original author or authors.
    + * Copyright 2002-2024 the original author or authors.
      *
      * Licensed under the Apache License, Version 2.0 (the "License");
      * you may not use this file except in compliance with the License.
    @@ -214,7 +214,7 @@ public void setMediaTypes(Properties mediaTypes) {
     	 * An alternative to {@link #setMediaTypes} for programmatic registrations.
     	 */
     	public void addMediaType(String key, MediaType mediaType) {
    -		this.mediaTypes.put(key.toLowerCase(Locale.ENGLISH), mediaType);
    +		this.mediaTypes.put(key.toLowerCase(Locale.ROOT), mediaType);
     	}
     
     	/**
    
  • spring-web/src/main/java/org/springframework/web/accept/MappingMediaTypeFileExtensionResolver.java+2 2 modified
    @@ -57,7 +57,7 @@ public MappingMediaTypeFileExtensionResolver(@Nullable Map<String, MediaType> me
     		if (mediaTypes != null) {
     			Set<String> allFileExtensions = new HashSet<>(mediaTypes.size());
     			mediaTypes.forEach((extension, mediaType) -> {
    -				String lowerCaseExtension = extension.toLowerCase(Locale.ENGLISH);
    +				String lowerCaseExtension = extension.toLowerCase(Locale.ROOT);
     				this.mediaTypes.put(lowerCaseExtension, mediaType);
     				addFileExtension(mediaType, lowerCaseExtension);
     				allFileExtensions.add(lowerCaseExtension);
    @@ -109,7 +109,7 @@ public List<String> getAllFileExtensions() {
     	 */
     	@Nullable
     	protected MediaType lookupMediaType(String extension) {
    -		return this.mediaTypes.get(extension.toLowerCase(Locale.ENGLISH));
    +		return this.mediaTypes.get(extension.toLowerCase(Locale.ROOT));
     	}
     
     }
    
  • spring-web/src/main/java/org/springframework/web/accept/PathExtensionContentNegotiationStrategy.java+2 2 modified
    @@ -1,5 +1,5 @@
     /*
    - * Copyright 2002-2020 the original author or authors.
    + * Copyright 2002-2024 the original author or authors.
      *
      * Licensed under the Apache License, Version 2.0 (the "License");
      * you may not use this file except in compliance with the License.
    @@ -99,7 +99,7 @@ protected String getMediaTypeKey(NativeWebRequest webRequest) {
     		// Ignore LOOKUP_PATH attribute, use our own "fixed" UrlPathHelper with decoding off
     		String path = this.urlPathHelper.getLookupPathForRequest(request);
     		String extension = UriUtils.extractFileExtension(path);
    -		return (StringUtils.hasText(extension) ? extension.toLowerCase(Locale.ENGLISH) : null);
    +		return (StringUtils.hasText(extension) ? extension.toLowerCase(Locale.ROOT) : null);
     	}
     
     	/**
    
  • spring-web/src/main/java/org/springframework/web/client/RestClientResponseException.java+1 1 modified
    @@ -105,7 +105,7 @@ public RestClientResponseException(
     	private static HttpHeaders copyHeaders(@Nullable HttpHeaders headers) {
     		if (headers != null) {
     			MultiValueMap<String, String> result =
    -					CollectionUtils.toMultiValueMap(new LinkedCaseInsensitiveMap<>(headers.size(), Locale.ENGLISH));
    +					CollectionUtils.toMultiValueMap(new LinkedCaseInsensitiveMap<>(headers.size(), Locale.ROOT));
     			headers.forEach((name, values) -> values.forEach(value -> result.add(name, value)));
     			return HttpHeaders.readOnlyHttpHeaders(result);
     		}
    
  • spring-web/src/main/java/org/springframework/web/filter/ForwardedHeaderFilter.java+2 2 modified
    @@ -82,7 +82,7 @@ public class ForwardedHeaderFilter extends OncePerRequestFilter {
     	private static final Log logger = LogFactory.getLog(ForwardedHeaderFilter.class);
     
     	private static final Set<String> FORWARDED_HEADER_NAMES =
    -			Collections.newSetFromMap(new LinkedCaseInsensitiveMap<>(10, Locale.ENGLISH));
    +			Collections.newSetFromMap(new LinkedCaseInsensitiveMap<>(10, Locale.ROOT));
     
     	static {
     		FORWARDED_HEADER_NAMES.add("Forwarded");
    @@ -204,7 +204,7 @@ public ForwardedHeaderRemovingRequest(HttpServletRequest request) {
     		}
     
     		private static Set<String> headerNames(HttpServletRequest request) {
    -			Set<String> headerNames = Collections.newSetFromMap(new LinkedCaseInsensitiveMap<>(Locale.ENGLISH));
    +			Set<String> headerNames = Collections.newSetFromMap(new LinkedCaseInsensitiveMap<>(Locale.ROOT));
     			Enumeration<String> names = request.getHeaderNames();
     			while (names.hasMoreElements()) {
     				String name = names.nextElement();
    
  • spring-web/src/main/java/org/springframework/web/filter/HiddenHttpMethodFilter.java+2 2 modified
    @@ -1,5 +1,5 @@
     /*
    - * Copyright 2002-2021 the original author or authors.
    + * Copyright 2002-2024 the original author or authors.
      *
      * Licensed under the Apache License, Version 2.0 (the "License");
      * you may not use this file except in compliance with the License.
    @@ -81,7 +81,7 @@ protected void doFilterInternal(HttpServletRequest request, HttpServletResponse
     		if ("POST".equals(request.getMethod()) && request.getAttribute(WebUtils.ERROR_EXCEPTION_ATTRIBUTE) == null) {
     			String paramValue = request.getParameter(this.methodParam);
     			if (StringUtils.hasLength(paramValue)) {
    -				String method = paramValue.toUpperCase(Locale.ENGLISH);
    +				String method = paramValue.toUpperCase(Locale.ROOT);
     				if (ALLOWED_METHODS.contains(method)) {
     					requestToUse = new HttpMethodRequestWrapper(request, method);
     				}
    
  • spring-web/src/main/java/org/springframework/web/filter/reactive/HiddenHttpMethodFilter.java+2 2 modified
    @@ -1,5 +1,5 @@
     /*
    - * Copyright 2002-2021 the original author or authors.
    + * Copyright 2002-2024 the original author or authors.
      *
      * Licensed under the Apache License, Version 2.0 (the "License");
      * you may not use this file except in compliance with the License.
    @@ -88,7 +88,7 @@ public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
     	}
     
     	private ServerWebExchange mapExchange(ServerWebExchange exchange, String methodParamValue) {
    -		HttpMethod httpMethod = HttpMethod.valueOf(methodParamValue.toUpperCase(Locale.ENGLISH));
    +		HttpMethod httpMethod = HttpMethod.valueOf(methodParamValue.toUpperCase(Locale.ROOT));
     		if (ALLOWED_METHODS.contains(httpMethod)) {
     			return exchange.mutate().request(builder -> builder.method(httpMethod)).build();
     		}
    
  • spring-web/src/main/java/org/springframework/web/multipart/support/MultipartResolutionDelegate.java+3 2 modified
    @@ -1,5 +1,5 @@
     /*
    - * Copyright 2002-2023 the original author or authors.
    + * Copyright 2002-2024 the original author or authors.
      *
      * Licensed under the Apache License, Version 2.0 (the "License");
      * you may not use this file except in compliance with the License.
    @@ -19,6 +19,7 @@
     import java.util.ArrayList;
     import java.util.Collection;
     import java.util.List;
    +import java.util.Locale;
     
     import jakarta.servlet.http.HttpServletRequest;
     import jakarta.servlet.http.Part;
    @@ -71,7 +72,7 @@ public static boolean isMultipartRequest(HttpServletRequest request) {
     
     	private static boolean isMultipartContent(HttpServletRequest request) {
     		String contentType = request.getContentType();
    -		return (contentType != null && contentType.toLowerCase().startsWith("multipart/"));
    +		return (contentType != null && contentType.toLowerCase(Locale.ROOT).startsWith("multipart/"));
     	}
     
     	static MultipartHttpServletRequest asMultipartHttpServletRequest(HttpServletRequest request) {
    
  • spring-web/src/main/java/org/springframework/web/multipart/support/StandardMultipartHttpServletRequest.java+2 1 modified
    @@ -28,6 +28,7 @@
     import java.util.Enumeration;
     import java.util.LinkedHashMap;
     import java.util.LinkedHashSet;
    +import java.util.Locale;
     import java.util.Map;
     import java.util.Set;
     
    @@ -117,7 +118,7 @@ protected void handleParseFailure(Throwable ex) {
     		do {
     			String msg = cause.getMessage();
     			if (msg != null) {
    -				msg = msg.toLowerCase();
    +				msg = msg.toLowerCase(Locale.ROOT);
     				if ((msg.contains("exceed") && (msg.contains("size") || msg.contains("length"))) ||
     						(msg.contains("request") && (msg.contains("big") || msg.contains("large")))) {
     					throw new MaxUploadSizeExceededException(-1, ex);
    
  • spring-web/src/main/java/org/springframework/web/server/adapter/ForwardedHeaderTransformer.java+1 1 modified
    @@ -61,7 +61,7 @@
     public class ForwardedHeaderTransformer implements Function<ServerHttpRequest, ServerHttpRequest> {
     
     	static final Set<String> FORWARDED_HEADER_NAMES =
    -			Collections.newSetFromMap(new LinkedCaseInsensitiveMap<>(10, Locale.ENGLISH));
    +			Collections.newSetFromMap(new LinkedCaseInsensitiveMap<>(10, Locale.ROOT));
     
     	static {
     		FORWARDED_HEADER_NAMES.add("Forwarded");
    
  • spring-web/src/main/java/org/springframework/web/util/DisconnectedClientHelper.java+2 1 modified
    @@ -16,6 +16,7 @@
     
     package org.springframework.web.util;
     
    +import java.util.Locale;
     import java.util.Set;
     
     import org.apache.commons.logging.Log;
    @@ -84,7 +85,7 @@ else if (logger.isDebugEnabled()) {
     	public static boolean isClientDisconnectedException(Throwable ex) {
     		String message = NestedExceptionUtils.getMostSpecificCause(ex).getMessage();
     		if (message != null) {
    -			String text = message.toLowerCase();
    +			String text = message.toLowerCase(Locale.ROOT);
     			for (String phrase : EXCEPTION_PHRASES) {
     				if (text.contains(phrase)) {
     					return true;
    
  • spring-web/src/main/java/org/springframework/web/util/UriComponentsBuilder.java+2 1 modified
    @@ -26,6 +26,7 @@
     import java.util.Deque;
     import java.util.HashMap;
     import java.util.List;
    +import java.util.Locale;
     import java.util.Map;
     import java.util.Optional;
     import java.util.regex.Matcher;
    @@ -282,7 +283,7 @@ public static UriComponentsBuilder fromHttpUrl(String httpUrl) {
     		if (matcher.matches()) {
     			UriComponentsBuilder builder = new UriComponentsBuilder();
     			String scheme = matcher.group(1);
    -			builder.scheme(scheme != null ? scheme.toLowerCase() : null);
    +			builder.scheme(scheme != null ? scheme.toLowerCase(Locale.ROOT) : null);
     			builder.userInfo(matcher.group(4));
     			String host = matcher.group(5);
     			checkSchemeAndHost(httpUrl, scheme, host);
    
  • spring-web/src/main/java/org/springframework/web/util/UrlPathHelper.java+3 2 modified
    @@ -1,5 +1,5 @@
     /*
    - * Copyright 2002-2023 the original author or authors.
    + * Copyright 2002-2024 the original author or authors.
      *
      * Licensed under the Apache License, Version 2.0 (the "License");
      * you may not use this file except in compliance with the License.
    @@ -18,6 +18,7 @@
     
     import java.net.URLDecoder;
     import java.nio.charset.UnsupportedCharsetException;
    +import java.util.Locale;
     import java.util.Map;
     import java.util.Properties;
     
    @@ -629,7 +630,7 @@ private static String removeSemicolonContentInternal(String requestUri) {
     
     	private String removeJsessionid(String requestUri) {
     		String key = ";jsessionid=";
    -		int index = requestUri.toLowerCase().indexOf(key);
    +		int index = requestUri.toLowerCase(Locale.ROOT).indexOf(key);
     		if (index == -1) {
     			return requestUri;
     		}
    
  • spring-web/src/test/java/org/springframework/http/client/AbstractHttpRequestFactoryTests.java+1 1 modified
    @@ -169,7 +169,7 @@ protected void assertHttpMethod(String path, HttpMethod method) throws Exception
     
     		try (ClientHttpResponse response = request.execute()) {
     			assertThat(response.getStatusCode()).as("Invalid response status").isEqualTo(HttpStatus.OK);
    -			assertThat(request.getMethod().name()).as("Invalid method").isEqualTo(path.toUpperCase(Locale.ENGLISH));
    +			assertThat(request.getMethod().name()).as("Invalid method").isEqualTo(path.toUpperCase(Locale.ROOT));
     		}
     	}
     
    

Vulnerability mechanics

Generated on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.

References

6

News mentions

0

No linked articles in our index yet.