VYPR
High severityNVD Advisory· Published Mar 16, 2024· Updated Feb 13, 2025

CVE-2024-22259: Spring Framework URL Parsing with Host Validation (2nd report)

CVE-2024-22259

Description

Applications that use UriComponentsBuilder in Spring Framework to parse an externally provided URL (e.g. through a query parameter) AND perform validation checks on the host of the parsed URL may be vulnerable to a open redirect https://cwe.mitre.org/data/definitions/601.html  attack or to a SSRF attack if the URL is used after passing validation checks.

This is the same as CVE-2024-22243 https://spring.io/security/cve-2024-22243 , but with different input.

AI Insight

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

Spring Framework's UriComponentsBuilder parses URLs in a way that host validation can be bypassed, leading to open redirect or SSRF attacks.

Vulnerability

Description

CVE-2024-22259 is a vulnerability in Spring Framework's UriComponentsBuilder that affects applications which parse an externally provided URL (e.g., through a query parameter) and then perform host validation checks on the parsed host. Due to an overly permissive regular expression used for extracting the host component, a specially crafted URL can cause the host to be parsed differently than expected, allowing an attacker to bypass the application's host validation. This is the same root cause as CVE-2024-22243 but triggered via a different input pattern [1].

Attack

Vector

The vulnerability is exploited by supplying a malicious URL that contains characters like @ or [ in a way that the regex HOST_IPV4_PATTERN or USERINFO_PATTERN no longer correctly identifies the host boundary. The fix involves tightening these regex patterns—for example, changing HOST_IPV4_PATTERN from [^\[/?#:]* to [^/?#:]* and USERINFO_PATTERN from ([^@/?#]*) to ([^/?#]*), as seen in the commit diffs [2][3][4]. An attacker can craft a URI such that the host portion appears valid to the application's validation logic but actually redirects to a different host when the URL is later used.

Impact

A successful exploit can lead to an open redirect (CWE-601) or a server-side request forgery (SSRF) attack, depending on how the parsed URL is used in the application. Open redirect allows an attacker to redirect users to a malicious site, while SSRF enables the attacker to make requests from the application's server to internal or external systems that would otherwise be blocked [1].

Mitigation

Spring Framework has released patches that modify the internal regex used by UriComponentsBuilder to ensure that the host extraction is robust. The fix is included in Spring Framework versions 6.1.5, 6.0.18, 5.3.34, and 5.2.25 (or later releases in the corresponding series). Users should upgrade to the patched versions. No workaround is available, as the vulnerability is in the framework's URL parsing logic [1][2][3][4].

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-webMaven
>= 6.1.0, < 6.1.56.1.5
org.springframework:spring-webMaven
>= 6.0.0, < 6.0.186.0.18
org.springframework:spring-webMaven
< 5.3.335.3.33

Affected products

12

Patches

3
381f790329a4

Extract reusable checkSchemeAndPort method

1 file changed · +14 8
  • spring-web/src/main/java/org/springframework/web/util/UriComponentsBuilder.java+14 8 modified
    @@ -76,9 +76,9 @@ public class UriComponentsBuilder implements UriBuilder, Cloneable {
     
     	private static final String HTTP_PATTERN = "(?i)(http|https):";
     
    -	private static final String USERINFO_PATTERN = "([^@/?#]*)";
    +	private static final String USERINFO_PATTERN = "([^/?#]*)";
     
    -	private static final String HOST_IPV4_PATTERN = "[^\\[/?#:]*";
    +	private static final String HOST_IPV4_PATTERN = "[^/?#:]*";
     
     	private static final String HOST_IPV6_PATTERN = "\\[[\\p{XDigit}:.]*[%\\p{Alnum}]*]";
     
    @@ -243,9 +243,7 @@ public static UriComponentsBuilder fromUriString(String uri) {
     				builder.schemeSpecificPart(ssp);
     			}
     			else {
    -				if (StringUtils.hasLength(scheme) && scheme.startsWith("http") && !StringUtils.hasLength(host)) {
    -					throw new IllegalArgumentException("[" + uri + "] is not a valid HTTP URL");
    -				}
    +				checkSchemeAndHost(uri, scheme, host);
     				builder.userInfo(userInfo);
     				builder.host(host);
     				if (StringUtils.hasLength(port)) {
    @@ -287,9 +285,7 @@ public static UriComponentsBuilder fromHttpUrl(String httpUrl) {
     			builder.scheme(scheme != null ? scheme.toLowerCase() : null);
     			builder.userInfo(matcher.group(4));
     			String host = matcher.group(5);
    -			if (StringUtils.hasLength(scheme) && !StringUtils.hasLength(host)) {
    -				throw new IllegalArgumentException("[" + httpUrl + "] is not a valid HTTP URL");
    -			}
    +			checkSchemeAndHost(httpUrl, scheme, host);
     			builder.host(host);
     			String port = matcher.group(7);
     			if (StringUtils.hasLength(port)) {
    @@ -308,6 +304,15 @@ public static UriComponentsBuilder fromHttpUrl(String httpUrl) {
     		}
     	}
     
    +	private static void checkSchemeAndHost(String uri, @Nullable String scheme, @Nullable String host) {
    +		if (StringUtils.hasLength(scheme) && scheme.startsWith("http") && !StringUtils.hasLength(host)) {
    +			throw new IllegalArgumentException("[" + uri + "] is not a valid HTTP URL");
    +		}
    +		if (StringUtils.hasLength(host) && host.startsWith("[") && !host.endsWith("]")) {
    +			throw new IllegalArgumentException("Invalid IPV6 host in [" + uri + "]");
    +		}
    +	}
    +
     	/**
     	 * Create a new {@code UriComponents} object from the URI associated with
     	 * the given HttpRequest while also overlaying with values from the headers
    @@ -363,6 +368,7 @@ public static UriComponentsBuilder fromOriginHeader(String origin) {
     			if (StringUtils.hasLength(port)) {
     				builder.port(port);
     			}
    +			checkSchemeAndHost(origin, scheme, host);
     			return builder;
     		}
     		else {
    
297cbae2990e

Extract reusable checkSchemeAndPort method

1 file changed · +14 8
  • spring-web/src/main/java/org/springframework/web/util/UriComponentsBuilder.java+14 8 modified
    @@ -77,9 +77,9 @@ public class UriComponentsBuilder implements UriBuilder, Cloneable {
     
     	private static final String HTTP_PATTERN = "(?i)(http|https):";
     
    -	private static final String USERINFO_PATTERN = "([^@/?#]*)";
    +	private static final String USERINFO_PATTERN = "([^/?#]*)";
     
    -	private static final String HOST_IPV4_PATTERN = "[^\\[/?#:]*";
    +	private static final String HOST_IPV4_PATTERN = "[^/?#:]*";
     
     	private static final String HOST_IPV6_PATTERN = "\\[[\\p{XDigit}:.]*[%\\p{Alnum}]*]";
     
    @@ -252,9 +252,7 @@ public static UriComponentsBuilder fromUriString(String uri) {
     				builder.schemeSpecificPart(ssp);
     			}
     			else {
    -				if (StringUtils.hasLength(scheme) && scheme.startsWith("http") && !StringUtils.hasLength(host)) {
    -					throw new IllegalArgumentException("[" + uri + "] is not a valid HTTP URL");
    -				}
    +				checkSchemeAndHost(uri, scheme, host);
     				builder.userInfo(userInfo);
     				builder.host(host);
     				if (StringUtils.hasLength(port)) {
    @@ -296,9 +294,7 @@ public static UriComponentsBuilder fromHttpUrl(String httpUrl) {
     			builder.scheme(scheme != null ? scheme.toLowerCase() : null);
     			builder.userInfo(matcher.group(4));
     			String host = matcher.group(5);
    -			if (StringUtils.hasLength(scheme) && !StringUtils.hasLength(host)) {
    -				throw new IllegalArgumentException("[" + httpUrl + "] is not a valid HTTP URL");
    -			}
    +			checkSchemeAndHost(httpUrl, scheme, host);
     			builder.host(host);
     			String port = matcher.group(7);
     			if (StringUtils.hasLength(port)) {
    @@ -317,6 +313,15 @@ public static UriComponentsBuilder fromHttpUrl(String httpUrl) {
     		}
     	}
     
    +	private static void checkSchemeAndHost(String uri, @Nullable String scheme, @Nullable String host) {
    +		if (StringUtils.hasLength(scheme) && scheme.startsWith("http") && !StringUtils.hasLength(host)) {
    +			throw new IllegalArgumentException("[" + uri + "] is not a valid HTTP URL");
    +		}
    +		if (StringUtils.hasLength(host) && host.startsWith("[") && !host.endsWith("]")) {
    +			throw new IllegalArgumentException("Invalid IPV6 host in [" + uri + "]");
    +		}
    +	}
    +
     	/**
     	 * Create a new {@code UriComponents} object from the URI associated with
     	 * the given HttpRequest while also overlaying with values from the headers
    @@ -402,6 +407,7 @@ public static UriComponentsBuilder fromOriginHeader(String origin) {
     			if (StringUtils.hasLength(port)) {
     				builder.port(port);
     			}
    +			checkSchemeAndHost(origin, scheme, host);
     			return builder;
     		}
     		else {
    
f2fd2f12269c

Extract reusable checkSchemeAndPort method

1 file changed · +14 8
  • spring-web/src/main/java/org/springframework/web/util/UriComponentsBuilder.java+14 8 modified
    @@ -77,9 +77,9 @@ public class UriComponentsBuilder implements UriBuilder, Cloneable {
     
     	private static final String HTTP_PATTERN = "(?i)(http|https):";
     
    -	private static final String USERINFO_PATTERN = "([^@/?#]*)";
    +	private static final String USERINFO_PATTERN = "([^/?#]*)";
     
    -	private static final String HOST_IPV4_PATTERN = "[^\\[/?#:]*";
    +	private static final String HOST_IPV4_PATTERN = "[^/?#:]*";
     
     	private static final String HOST_IPV6_PATTERN = "\\[[\\p{XDigit}:.]*[%\\p{Alnum}]*]";
     
    @@ -252,9 +252,7 @@ public static UriComponentsBuilder fromUriString(String uri) {
     				builder.schemeSpecificPart(ssp);
     			}
     			else {
    -				if (StringUtils.hasLength(scheme) && scheme.startsWith("http") && !StringUtils.hasLength(host)) {
    -					throw new IllegalArgumentException("[" + uri + "] is not a valid HTTP URL");
    -				}
    +				checkSchemeAndHost(uri, scheme, host);
     				builder.userInfo(userInfo);
     				builder.host(host);
     				if (StringUtils.hasLength(port)) {
    @@ -296,9 +294,7 @@ public static UriComponentsBuilder fromHttpUrl(String httpUrl) {
     			builder.scheme(scheme != null ? scheme.toLowerCase() : null);
     			builder.userInfo(matcher.group(4));
     			String host = matcher.group(5);
    -			if (StringUtils.hasLength(scheme) && !StringUtils.hasLength(host)) {
    -				throw new IllegalArgumentException("[" + httpUrl + "] is not a valid HTTP URL");
    -			}
    +			checkSchemeAndHost(httpUrl, scheme, host);
     			builder.host(host);
     			String port = matcher.group(7);
     			if (StringUtils.hasLength(port)) {
    @@ -317,6 +313,15 @@ public static UriComponentsBuilder fromHttpUrl(String httpUrl) {
     		}
     	}
     
    +	private static void checkSchemeAndHost(String uri, @Nullable String scheme, @Nullable String host) {
    +		if (StringUtils.hasLength(scheme) && scheme.startsWith("http") && !StringUtils.hasLength(host)) {
    +			throw new IllegalArgumentException("[" + uri + "] is not a valid HTTP URL");
    +		}
    +		if (StringUtils.hasLength(host) && host.startsWith("[") && !host.endsWith("]")) {
    +			throw new IllegalArgumentException("Invalid IPV6 host in [" + uri + "]");
    +		}
    +	}
    +
     	/**
     	 * Create a new {@code UriComponents} object from the URI associated with
     	 * the given HttpRequest while also overlaying with values from the headers
    @@ -402,6 +407,7 @@ public static UriComponentsBuilder fromOriginHeader(String origin) {
     			if (StringUtils.hasLength(port)) {
     				builder.port(port);
     			}
    +			checkSchemeAndHost(origin, scheme, host);
     			return builder;
     		}
     		else {
    

Vulnerability mechanics

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

References

8

News mentions

0

No linked articles in our index yet.