From 2d27040121496b2ebd7adc1187e2a8ba9545e84e Mon Sep 17 00:00:00 2001 From: v146kuma Date: Thu, 25 Dec 2025 11:26:18 +0530 Subject: [PATCH 1/3] Fix CVEs for 5.8.x using Nokia Spring Framework --- ...tFallbackMethodSecurityMetadataSource.java | 16 +++++-- ...tingMethodSecurityMetadataSourceTests.java | 46 +++++++++++++++++-- .../security/crypto/bcrypt/BCrypt.java | 5 +- .../bcrypt/BCryptPasswordEncoderTests.java | 32 +++++++++++++ 4 files changed, 90 insertions(+), 9 deletions(-) diff --git a/core/src/main/java/org/springframework/security/access/method/AbstractFallbackMethodSecurityMetadataSource.java b/core/src/main/java/org/springframework/security/access/method/AbstractFallbackMethodSecurityMetadataSource.java index ef2feb7505f..b8a8e8adbac 100644 --- a/core/src/main/java/org/springframework/security/access/method/AbstractFallbackMethodSecurityMetadataSource.java +++ b/core/src/main/java/org/springframework/security/access/method/AbstractFallbackMethodSecurityMetadataSource.java @@ -21,8 +21,10 @@ import java.util.Collections; import org.springframework.aop.support.AopUtils; +import org.springframework.core.BridgeMethodResolver; import org.springframework.security.access.ConfigAttribute; import org.springframework.security.authorization.AuthorizationManager; +import org.springframework.util.ClassUtils; /** * Abstract implementation of {@link MethodSecurityMetadataSource} that supports both @@ -53,10 +55,16 @@ public abstract class AbstractFallbackMethodSecurityMetadataSource extends Abstr @Override public Collection getAttributes(Method method, Class targetClass) { - // The method may be on an interface, but we need attributes from the target - // class. - // If the target class is null, the method will be unchanged. - Method specificMethod = AopUtils.getMostSpecificMethod(method, targetClass); + // 1. Resolve Bridge Method first (Standard Spring AOP step) + Method specificMethod = BridgeMethodResolver + .findBridgedMethod(AopUtils.getMostSpecificMethod(method, targetClass)); + + // 2. NEW FIX for CVE-2025-41248: Resolve Generic Parameters + // This ensures that if the method is generic (e.g. save(T)), we map it + // to the concrete implementation (e.g. save(String)) to find annotations + // correctly. + specificMethod = ClassUtils.getMostSpecificMethod(specificMethod, targetClass); + // First try is the method in the target class. Collection attr = findAttributes(specificMethod, targetClass); if (attr != null) { diff --git a/core/src/test/java/org/springframework/security/access/method/DelegatingMethodSecurityMetadataSourceTests.java b/core/src/test/java/org/springframework/security/access/method/DelegatingMethodSecurityMetadataSourceTests.java index 3d388d2f48b..cde335c5299 100644 --- a/core/src/test/java/org/springframework/security/access/method/DelegatingMethodSecurityMetadataSourceTests.java +++ b/core/src/test/java/org/springframework/security/access/method/DelegatingMethodSecurityMetadataSourceTests.java @@ -17,17 +17,16 @@ package org.springframework.security.access.method; import java.lang.reflect.Method; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; +import java.util.*; import org.aopalliance.intercept.MethodInvocation; import org.junit.jupiter.api.Test; import org.mockito.ArgumentMatchers; import org.springframework.security.access.ConfigAttribute; +import org.springframework.security.access.SecurityConfig; import org.springframework.security.util.SimpleMethodInvocation; +import org.springframework.util.ClassUtils; import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.BDDMockito.given; @@ -77,4 +76,43 @@ public void returnsDelegateAttributes() throws Exception { .isEmpty(); } + // TEST FOR CVE-2025-41248 + @Test + public void getAttributesWithParameterizedTypeLocatesAnnotation() throws Exception { + // 1. Set up the delegate and the delegator + List sources = new ArrayList<>(); + MethodSecurityMetadataSource delegate = mock(MethodSecurityMetadataSource.class); + sources.add(delegate); + this.mds = new DelegatingMethodSecurityMetadataSource(sources); + + // 2. Create the scenario: A generic interface and a concrete implementation + Method method = ClassUtils.getMethod(GenericServiceImpl.class, "handle", String.class); + ConfigAttribute ca = new SecurityConfig("ROLE_USER"); + List expectedAttributes = Arrays.asList(ca); + + // 3. Stub the delegate + given(delegate.getAttributes(method, GenericServiceImpl.class)).willReturn(expectedAttributes); + + // 4. Execute + MethodInvocation mi = new SimpleMethodInvocation(new GenericServiceImpl(), method); + Collection actualAttributes = this.mds.getAttributes(mi); + + // 5. Verify: Corrected comparison logic + assertThat(actualAttributes).containsExactlyElementsOf(expectedAttributes); + } + + private interface GenericService { + + void handle(T input); + + } + + private static class GenericServiceImpl implements GenericService { + + @Override + public void handle(String input) { + } + + } + } diff --git a/crypto/src/main/java/org/springframework/security/crypto/bcrypt/BCrypt.java b/crypto/src/main/java/org/springframework/security/crypto/bcrypt/BCrypt.java index 0f8d082fdf0..6eac349070a 100644 --- a/crypto/src/main/java/org/springframework/security/crypto/bcrypt/BCrypt.java +++ b/crypto/src/main/java/org/springframework/security/crypto/bcrypt/BCrypt.java @@ -610,7 +610,10 @@ private static String hashpw(byte passwordb[], String salt, boolean for_check) { char minor = (char) 0; int rounds, off; StringBuilder rs = new StringBuilder(); - + // FIX for CVE-2025-22228 (The Bypass) AND CVE-2025-22234 (The Timing Mitigation) + if (!for_check && passwordb.length > 72) { + throw new IllegalArgumentException("password cannot be more than 72 bytes"); + } if (salt == null) { throw new IllegalArgumentException("salt cannot be null"); } diff --git a/crypto/src/test/java/org/springframework/security/crypto/bcrypt/BCryptPasswordEncoderTests.java b/crypto/src/test/java/org/springframework/security/crypto/bcrypt/BCryptPasswordEncoderTests.java index b3780847d91..7a1ff320cac 100644 --- a/crypto/src/test/java/org/springframework/security/crypto/bcrypt/BCryptPasswordEncoderTests.java +++ b/crypto/src/test/java/org/springframework/security/crypto/bcrypt/BCryptPasswordEncoderTests.java @@ -222,4 +222,36 @@ public void checkWhenNoRoundsThenTrue() { assertThat(encoder.matches("wrong", "$2a$00$9N8N35BVs5TLqGL3pspAte5OWWA2a2aZIs.EGp7At7txYakFERMue")).isFalse(); } + // FIX for CVE-2025-22228 (The Bypass) AND CVE-2025-22234 (The Timing Mitigation) + @Test + public void encodeWhenPasswordOverMaxLengthThenThrowIllegalArgumentException() { + BCryptPasswordEncoder encoder = new BCryptPasswordEncoder(); + + String password72chars = "123456789012345678901234567890123456789012345678901234567890123456789012"; + encoder.encode(password72chars); + + String password73chars = password72chars + "3"; + assertThatIllegalArgumentException().isThrownBy(() -> encoder.encode(password73chars)); + } + + @Test + public void matchesWhenPasswordOverMaxLengthThenAllowToMatch() { + BCryptPasswordEncoder encoder = new BCryptPasswordEncoder(); + + String password71chars = "12345678901234567890123456789012345678901234567890123456789012345678901"; + String encodedPassword71chars = "$2a$10$jx3x2FaF.iX5QZ9i3O424Os2Ou5P5JrnedmWYHuDyX8JKA4Unp4xq"; + assertThat(encoder.matches(password71chars, encodedPassword71chars)).isTrue(); + + String password72chars = password71chars + "2"; + String encodedPassword72chars = "$2a$10$oXYO6/UvbsH5rQEraBkl6uheccBqdB3n.RaWbrimog9hS2GX4lo/O"; + assertThat(encoder.matches(password72chars, encodedPassword72chars)).isTrue(); + + // Max length is 72 bytes, however, we need to ensure backwards compatibility + // for previously encoded passwords that are greater than 72 bytes and allow the + // match to be performed. + String password73chars = password72chars + "3"; + String encodedPassword73chars = "$2a$10$1l9.kvQTsqNLiCYFqmKtQOHkp.BrgIrwsnTzWo9jdbQRbuBYQ/AVK"; + assertThat(encoder.matches(password73chars, encodedPassword73chars)).isTrue(); + } + } From bf61708ebd1f912025c3303dc6546a13a5dbf527 Mon Sep 17 00:00:00 2001 From: v146kuma Date: Fri, 26 Dec 2025 14:41:45 +0530 Subject: [PATCH 2/3] Fix CVEs for 5.8.x using Nokia Spring Framework --- ...tFallbackMethodSecurityMetadataSource.java | 16 ++----- ...tingMethodSecurityMetadataSourceTests.java | 46 ++----------------- 2 files changed, 8 insertions(+), 54 deletions(-) diff --git a/core/src/main/java/org/springframework/security/access/method/AbstractFallbackMethodSecurityMetadataSource.java b/core/src/main/java/org/springframework/security/access/method/AbstractFallbackMethodSecurityMetadataSource.java index b8a8e8adbac..ef2feb7505f 100644 --- a/core/src/main/java/org/springframework/security/access/method/AbstractFallbackMethodSecurityMetadataSource.java +++ b/core/src/main/java/org/springframework/security/access/method/AbstractFallbackMethodSecurityMetadataSource.java @@ -21,10 +21,8 @@ import java.util.Collections; import org.springframework.aop.support.AopUtils; -import org.springframework.core.BridgeMethodResolver; import org.springframework.security.access.ConfigAttribute; import org.springframework.security.authorization.AuthorizationManager; -import org.springframework.util.ClassUtils; /** * Abstract implementation of {@link MethodSecurityMetadataSource} that supports both @@ -55,16 +53,10 @@ public abstract class AbstractFallbackMethodSecurityMetadataSource extends Abstr @Override public Collection getAttributes(Method method, Class targetClass) { - // 1. Resolve Bridge Method first (Standard Spring AOP step) - Method specificMethod = BridgeMethodResolver - .findBridgedMethod(AopUtils.getMostSpecificMethod(method, targetClass)); - - // 2. NEW FIX for CVE-2025-41248: Resolve Generic Parameters - // This ensures that if the method is generic (e.g. save(T)), we map it - // to the concrete implementation (e.g. save(String)) to find annotations - // correctly. - specificMethod = ClassUtils.getMostSpecificMethod(specificMethod, targetClass); - + // The method may be on an interface, but we need attributes from the target + // class. + // If the target class is null, the method will be unchanged. + Method specificMethod = AopUtils.getMostSpecificMethod(method, targetClass); // First try is the method in the target class. Collection attr = findAttributes(specificMethod, targetClass); if (attr != null) { diff --git a/core/src/test/java/org/springframework/security/access/method/DelegatingMethodSecurityMetadataSourceTests.java b/core/src/test/java/org/springframework/security/access/method/DelegatingMethodSecurityMetadataSourceTests.java index cde335c5299..3d388d2f48b 100644 --- a/core/src/test/java/org/springframework/security/access/method/DelegatingMethodSecurityMetadataSourceTests.java +++ b/core/src/test/java/org/springframework/security/access/method/DelegatingMethodSecurityMetadataSourceTests.java @@ -17,16 +17,17 @@ package org.springframework.security.access.method; import java.lang.reflect.Method; -import java.util.*; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; import org.aopalliance.intercept.MethodInvocation; import org.junit.jupiter.api.Test; import org.mockito.ArgumentMatchers; import org.springframework.security.access.ConfigAttribute; -import org.springframework.security.access.SecurityConfig; import org.springframework.security.util.SimpleMethodInvocation; -import org.springframework.util.ClassUtils; import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.BDDMockito.given; @@ -76,43 +77,4 @@ public void returnsDelegateAttributes() throws Exception { .isEmpty(); } - // TEST FOR CVE-2025-41248 - @Test - public void getAttributesWithParameterizedTypeLocatesAnnotation() throws Exception { - // 1. Set up the delegate and the delegator - List sources = new ArrayList<>(); - MethodSecurityMetadataSource delegate = mock(MethodSecurityMetadataSource.class); - sources.add(delegate); - this.mds = new DelegatingMethodSecurityMetadataSource(sources); - - // 2. Create the scenario: A generic interface and a concrete implementation - Method method = ClassUtils.getMethod(GenericServiceImpl.class, "handle", String.class); - ConfigAttribute ca = new SecurityConfig("ROLE_USER"); - List expectedAttributes = Arrays.asList(ca); - - // 3. Stub the delegate - given(delegate.getAttributes(method, GenericServiceImpl.class)).willReturn(expectedAttributes); - - // 4. Execute - MethodInvocation mi = new SimpleMethodInvocation(new GenericServiceImpl(), method); - Collection actualAttributes = this.mds.getAttributes(mi); - - // 5. Verify: Corrected comparison logic - assertThat(actualAttributes).containsExactlyElementsOf(expectedAttributes); - } - - private interface GenericService { - - void handle(T input); - - } - - private static class GenericServiceImpl implements GenericService { - - @Override - public void handle(String input) { - } - - } - } From 6999bdce0630dd1a0e6ac495ec8924e54996c99e Mon Sep 17 00:00:00 2001 From: v146kuma Date: Fri, 26 Dec 2025 19:22:16 +0530 Subject: [PATCH 3/3] updating readme --- README.adoc | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/README.adoc b/README.adoc index cff325480b6..a07ccefc493 100644 --- a/README.adoc +++ b/README.adoc @@ -65,3 +65,8 @@ https://help.github.com/articles/creating-a-pull-request[Pull requests] are welc == License Spring Security is Open Source software released under the https://www.apache.org/licenses/LICENSE-2.0.html[Apache 2.0 license]. + +=== Vulnerabilities Fixes By Nokia +* Fixing the below Vulnerabilities. + * https://spring.io/security/cve-2025-22228/ + * https://spring.io/security/cve-2025-22234/