VYPR
High severity7.5GHSA Advisory· Published Sep 16, 2025· Updated Apr 15, 2026

CVE-2025-41248

CVE-2025-41248

Description

The Spring Security annotation detection mechanism may not correctly resolve annotations on methods within type hierarchies with a parameterized super type with unbounded generics. This can be an issue when using @PreAuthorize and other method security annotations, resulting in an authorization bypass.

Your application may be affected by this if you are using Spring Security's @EnableMethodSecurity feature.

You are not affected by this if you are not using @EnableMethodSecurity or if you do not use security annotations on methods in generic superclasses or generic interfaces.

This CVE is published in conjunction with CVE-2025-41249 https://spring.io/security/cve-2025-41249 .

Affected packages

Versions sourced from the GitHub Security Advisory.

PackageAffected versionsPatched versions
org.springframework.security:spring-security-coreMaven
>= 6.4.0, < 6.4.106.4.10
org.springframework.security:spring-security-coreMaven
>= 6.5.0, < 6.5.46.5.4

Affected products

1

Patches

2
d0f93fa6d833

Merge branch '6.4.x' into 6.5.x

2 files changed · +33 1
  • core/src/main/java/org/springframework/security/core/annotation/UniqueSecurityAnnotationScanner.java+1 1 modified
    @@ -305,7 +305,7 @@ private static boolean hasSameGenericTypeParameters(Method rootMethod, Method ca
     		}
     		for (int i = 0; i < rootParameterTypes.length; i++) {
     			Class<?> resolvedParameterType = ResolvableType.forMethodParameter(candidateMethod, i, sourceDeclaringClass)
    -				.resolve();
    +				.toClass();
     			if (rootParameterTypes[i] != resolvedParameterType) {
     				return false;
     			}
    
  • core/src/test/java/org/springframework/security/core/annotation/UniqueSecurityAnnotationScannerTests.java+32 0 modified
    @@ -28,6 +28,7 @@
     
     import org.springframework.core.annotation.AnnotationConfigurationException;
     import org.springframework.security.access.prepost.PreAuthorize;
    +import org.springframework.util.ClassUtils;
     
     import static org.assertj.core.api.Assertions.assertThat;
     import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
    @@ -326,6 +327,14 @@ void scanParameterAnnotationWhenPresentInParentAndInterfaceThenException() throw
     			.isThrownBy(() -> this.parameterScanner.scan(parameter));
     	}
     
    +	// gh-17898
    +	@Test
    +	void scanWhenAnnotationOnParameterizedUndeclaredMethodAndThenLocates() throws Exception {
    +		Method method = ClassUtils.getMethod(GenericInterfaceImpl.class, "processOneAndTwo", Long.class, Object.class);
    +		PreAuthorize pre = this.scanner.scan(method, method.getDeclaringClass());
    +		assertThat(pre).isNotNull();
    +	}
    +
     	interface UserService {
     
     		void add(@CustomParameterAnnotation("one") String user);
    @@ -764,4 +773,27 @@ <S extends Number> S getExtByClass(Class<S> clazz, Long l) {
     
     	}
     
    +	interface GenericInterface<A, B> {
    +
    +		@PreAuthorize("hasAuthority('thirtythree')")
    +		void processOneAndTwo(A value1, B value2);
    +
    +	}
    +
    +	abstract static class GenericAbstractSuperclass<C> implements GenericInterface<Long, C> {
    +
    +		@Override
    +		public void processOneAndTwo(Long value1, C value2) {
    +		}
    +
    +	}
    +
    +	static class GenericInterfaceImpl extends GenericAbstractSuperclass<String> {
    +
    +		// The compiler does not require us to declare a concrete
    +		// processOneAndTwo(Long, String) method, and we intentionally
    +		// do not declare one here.
    +
    +	}
    +
     }
    
e5694ac7b5e4

Fallback to Object When Determining Overridden Methods

2 files changed · +33 1
  • core/src/main/java/org/springframework/security/core/annotation/UniqueSecurityAnnotationScanner.java+1 1 modified
    @@ -252,7 +252,7 @@ private static boolean hasSameGenericTypeParameters(Method rootMethod, Method ca
     		}
     		for (int i = 0; i < rootParameterTypes.length; i++) {
     			Class<?> resolvedParameterType = ResolvableType.forMethodParameter(candidateMethod, i, sourceDeclaringClass)
    -				.resolve();
    +				.toClass();
     			if (rootParameterTypes[i] != resolvedParameterType) {
     				return false;
     			}
    
  • core/src/test/java/org/springframework/security/core/annotation/UniqueSecurityAnnotationScannerTests.java+32 0 modified
    @@ -22,6 +22,7 @@
     
     import org.springframework.core.annotation.AnnotationConfigurationException;
     import org.springframework.security.access.prepost.PreAuthorize;
    +import org.springframework.util.ClassUtils;
     
     import static org.assertj.core.api.Assertions.assertThat;
     import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
    @@ -275,6 +276,14 @@ void scanWhenAnnotationOnParameterizedMethodThenLocates() throws Exception {
     		assertThat(pre).isNotNull();
     	}
     
    +	// gh-17898
    +	@Test
    +	void scanWhenAnnotationOnParameterizedUndeclaredMethodAndThenLocates() throws Exception {
    +		Method method = ClassUtils.getMethod(GenericInterfaceImpl.class, "processOneAndTwo", Long.class, Object.class);
    +		PreAuthorize pre = this.scanner.scan(method, method.getDeclaringClass());
    +		assertThat(pre).isNotNull();
    +	}
    +
     	@PreAuthorize("one")
     	private interface AnnotationOnInterface {
     
    @@ -637,4 +646,27 @@ <S extends Number> S getExtByClass(Class<S> clazz, Long l) {
     
     	}
     
    +	interface GenericInterface<A, B> {
    +
    +		@PreAuthorize("hasAuthority('thirtythree')")
    +		void processOneAndTwo(A value1, B value2);
    +
    +	}
    +
    +	abstract static class GenericAbstractSuperclass<C> implements GenericInterface<Long, C> {
    +
    +		@Override
    +		public void processOneAndTwo(Long value1, C value2) {
    +		}
    +
    +	}
    +
    +	static class GenericInterfaceImpl extends GenericAbstractSuperclass<String> {
    +
    +		// The compiler does not require us to declare a concrete
    +		// processOneAndTwo(Long, String) method, and we intentionally
    +		// do not declare one here.
    +
    +	}
    +
     }
    

Vulnerability mechanics

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

References

9

News mentions

0

No linked articles in our index yet.