From 7c28b154716ce0542fa450587b1193f463a0f383 Mon Sep 17 00:00:00 2001 From: johnycho Date: Sat, 10 Jan 2026 17:24:37 +0900 Subject: [PATCH 1/3] Improve serialVersionUID check in tests Signed-off-by: johnycho --- .../security/SpringSecurityCoreVersionSerializableTests.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/config/src/test/java/org/springframework/security/SpringSecurityCoreVersionSerializableTests.java b/config/src/test/java/org/springframework/security/SpringSecurityCoreVersionSerializableTests.java index 85714f4124..0306bed51a 100644 --- a/config/src/test/java/org/springframework/security/SpringSecurityCoreVersionSerializableTests.java +++ b/config/src/test/java/org/springframework/security/SpringSecurityCoreVersionSerializableTests.java @@ -36,6 +36,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.HashSet; import java.util.List; +import java.util.Objects; import java.util.Set; import java.util.stream.Stream; @@ -208,8 +209,8 @@ class SpringSecurityCoreVersionSerializableTests { .map(Field::getName) .anyMatch((n) -> n.equals("serialVersionUID")); SuppressWarnings suppressWarnings = clazz.getAnnotation(SuppressWarnings.class); - boolean hasSerialIgnore = suppressWarnings == null - || Arrays.asList(suppressWarnings.value()).contains("Serial"); + boolean hasSerialIgnore = Objects.nonNull(suppressWarnings) + && Arrays.asList(suppressWarnings.value()).contains("serial"); if (!hasSerialVersion && !hasSerialIgnore) { classes.add(clazz); continue; From 0b680be97b4e48474dafdf917fdb13da501c558d Mon Sep 17 00:00:00 2001 From: Josh Cummings <3627351+jzheaux@users.noreply.github.com> Date: Mon, 30 Mar 2026 17:14:03 -0600 Subject: [PATCH 2/3] Update Test to find SuppressWarnings Signed-off-by: Josh Cummings <3627351+jzheaux@users.noreply.github.com> --- ...gSecurityCoreVersionSerializableTests.java | 60 +++++++++++++++++-- 1 file changed, 54 insertions(+), 6 deletions(-) diff --git a/config/src/test/java/org/springframework/security/SpringSecurityCoreVersionSerializableTests.java b/config/src/test/java/org/springframework/security/SpringSecurityCoreVersionSerializableTests.java index 0306bed51a..daa733675d 100644 --- a/config/src/test/java/org/springframework/security/SpringSecurityCoreVersionSerializableTests.java +++ b/config/src/test/java/org/springframework/security/SpringSecurityCoreVersionSerializableTests.java @@ -33,11 +33,10 @@ import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.util.ArrayList; -import java.util.Arrays; import java.util.HashSet; import java.util.List; -import java.util.Objects; import java.util.Set; +import java.util.regex.Pattern; import java.util.stream.Stream; import org.apache.commons.lang3.ObjectUtils; @@ -208,10 +207,7 @@ class SpringSecurityCoreVersionSerializableTests { boolean hasSerialVersion = Stream.of(clazz.getDeclaredFields()) .map(Field::getName) .anyMatch((n) -> n.equals("serialVersionUID")); - SuppressWarnings suppressWarnings = clazz.getAnnotation(SuppressWarnings.class); - boolean hasSerialIgnore = Objects.nonNull(suppressWarnings) - && Arrays.asList(suppressWarnings.value()).contains("serial"); - if (!hasSerialVersion && !hasSerialIgnore) { + if (!hasSerialVersion && !hasSuppressSerialInSource(clazz)) { classes.add(clazz); continue; } @@ -250,6 +246,58 @@ class SpringSecurityCoreVersionSerializableTests { return classes.stream(); } + private static boolean hasSuppressSerialInSource(Class clazz) { + try { + Class fileClass = clazz; + while (fileClass.getEnclosingClass() != null) { + fileClass = fileClass.getEnclosingClass(); + } + var codeSource = fileClass.getProtectionDomain().getCodeSource(); + if (codeSource == null) { + return false; + } + Path sourceFile = findSourceFile(Path.of(codeSource.getLocation().toURI()), fileClass); + if (sourceFile == null) { + return false; + } + return hasSuppressSerialAnnotation(Files.readAllLines(sourceFile), clazz.getSimpleName()); + } + catch (Exception ex) { + return false; + } + } + + private static Path findSourceFile(Path start, Class clazz) { + String relativePath = clazz.getName().replace('.', '/') + ".java"; + Path dir = start; + for (int i = 0; i < 10 && dir != null; i++) { + for (String sourceRoot : List.of("src/main/java", "src/test/java")) { + Path candidate = dir.resolve(sourceRoot).resolve(relativePath); + if (Files.exists(candidate)) { + return candidate; + } + } + dir = dir.getParent(); + } + return null; + } + + private static boolean hasSuppressSerialAnnotation(List lines, String simpleClassName) { + Pattern classDeclaration = Pattern + .compile("\\b(?:class|interface|enum|record)\\s+" + Pattern.quote(simpleClassName) + "\\b"); + for (int i = 0; i < lines.size(); i++) { + if (classDeclaration.matcher(lines.get(i)).find()) { + for (int j = Math.max(0, i - 5); j < i; j++) { + String line = lines.get(j); + if (line.contains("@SuppressWarnings") && line.contains("\"serial\"")) { + return true; + } + } + } + } + return false; + } + private static String getCurrentVersion() { String version = System.getProperty("springSecurityVersion"); String[] parts = version.split("\\."); From 52d98ab7afd020af919462c91b0f05e585fa1628 Mon Sep 17 00:00:00 2001 From: Josh Cummings <3627351+jzheaux@users.noreply.github.com> Date: Mon, 30 Mar 2026 17:14:17 -0600 Subject: [PATCH 3/3] Add Needed SuppressWarnings Annotations Signed-off-by: Josh Cummings <3627351+jzheaux@users.noreply.github.com> --- .../method/ExpressionAttributeAuthorizationDecision.java | 1 + .../client/web/OAuth2AuthorizationRequestRedirectFilter.java | 1 + .../security/oauth2/jwt/DPoPProofJwtDecoderFactory.java | 1 + .../service/registration/OpenSamlRelyingPartyRegistration.java | 1 + .../web/access/expression/WebExpressionConfigAttribute.java | 1 + 5 files changed, 5 insertions(+) diff --git a/core/src/main/java/org/springframework/security/authorization/method/ExpressionAttributeAuthorizationDecision.java b/core/src/main/java/org/springframework/security/authorization/method/ExpressionAttributeAuthorizationDecision.java index 6eff3cc8ae..5cf340520e 100644 --- a/core/src/main/java/org/springframework/security/authorization/method/ExpressionAttributeAuthorizationDecision.java +++ b/core/src/main/java/org/springframework/security/authorization/method/ExpressionAttributeAuthorizationDecision.java @@ -28,6 +28,7 @@ import org.springframework.security.authorization.AuthorizationDecision; * instead */ @Deprecated +@SuppressWarnings("serial") public class ExpressionAttributeAuthorizationDecision extends AuthorizationDecision { private final ExpressionAttribute expressionAttribute; diff --git a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/web/OAuth2AuthorizationRequestRedirectFilter.java b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/web/OAuth2AuthorizationRequestRedirectFilter.java index 0757ae4693..434e4bc3fe 100644 --- a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/web/OAuth2AuthorizationRequestRedirectFilter.java +++ b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/web/OAuth2AuthorizationRequestRedirectFilter.java @@ -269,6 +269,7 @@ public class OAuth2AuthorizationRequestRedirectFilter extends OncePerRequestFilt } + @SuppressWarnings("serial") private static final class OAuth2AuthorizationRequestException extends AuthenticationException { OAuth2AuthorizationRequestException(Throwable cause) { diff --git a/oauth2/oauth2-jose/src/main/java/org/springframework/security/oauth2/jwt/DPoPProofJwtDecoderFactory.java b/oauth2/oauth2-jose/src/main/java/org/springframework/security/oauth2/jwt/DPoPProofJwtDecoderFactory.java index be89885b7b..de88ba57ae 100644 --- a/oauth2/oauth2-jose/src/main/java/org/springframework/security/oauth2/jwt/DPoPProofJwtDecoderFactory.java +++ b/oauth2/oauth2-jose/src/main/java/org/springframework/security/oauth2/jwt/DPoPProofJwtDecoderFactory.java @@ -185,6 +185,7 @@ public final class DPoPProofJwtDecoderFactory implements JwtDecoderFactory { private static final int MAX_SIZE = 1000; diff --git a/saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/registration/OpenSamlRelyingPartyRegistration.java b/saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/registration/OpenSamlRelyingPartyRegistration.java index 03e4a54172..448ff5340a 100644 --- a/saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/registration/OpenSamlRelyingPartyRegistration.java +++ b/saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/registration/OpenSamlRelyingPartyRegistration.java @@ -42,6 +42,7 @@ import org.springframework.security.saml2.core.Saml2X509Credential; * */ @Deprecated +@SuppressWarnings("serial") public final class OpenSamlRelyingPartyRegistration extends RelyingPartyRegistration { OpenSamlRelyingPartyRegistration(RelyingPartyRegistration registration) { diff --git a/web/src/main/java/org/springframework/security/web/access/expression/WebExpressionConfigAttribute.java b/web/src/main/java/org/springframework/security/web/access/expression/WebExpressionConfigAttribute.java index 9a71c98480..94e54d524f 100644 --- a/web/src/main/java/org/springframework/security/web/access/expression/WebExpressionConfigAttribute.java +++ b/web/src/main/java/org/springframework/security/web/access/expression/WebExpressionConfigAttribute.java @@ -32,6 +32,7 @@ import org.springframework.security.web.FilterInvocation; * {@link AuthorizationManager}. */ @Deprecated +@SuppressWarnings("serial") class WebExpressionConfigAttribute implements ConfigAttribute, EvaluationContextPostProcessor { private final Expression authorizeExpression;