diff --git a/core/src/main/java/org/springframework/security/authorization/method/PostFilterAuthorizationMethodInterceptor.java b/core/src/main/java/org/springframework/security/authorization/method/PostFilterAuthorizationMethodInterceptor.java index 0264e6ecebe..d05a2a26ffc 100644 --- a/core/src/main/java/org/springframework/security/authorization/method/PostFilterAuthorizationMethodInterceptor.java +++ b/core/src/main/java/org/springframework/security/authorization/method/PostFilterAuthorizationMethodInterceptor.java @@ -21,6 +21,8 @@ import org.aopalliance.aop.Advice; import org.aopalliance.intercept.MethodInterceptor; import org.aopalliance.intercept.MethodInvocation; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; import org.jspecify.annotations.Nullable; import org.springframework.aop.Pointcut; @@ -44,6 +46,8 @@ */ public final class PostFilterAuthorizationMethodInterceptor implements AuthorizationAdvisor { + private final Log logger = LogFactory.getLog(getClass()); + private Supplier securityContextHolderStrategy = SecurityContextHolder::getContextHolderStrategy; private PostFilterExpressionAttributeRegistry registry = new PostFilterExpressionAttributeRegistry(); @@ -133,6 +137,10 @@ public void setSecurityContextHolderStrategy(SecurityContextHolderStrategy strat if (attribute == null) { return returnedObject; } + if (returnedObject == null) { + this.logger.debug("Returned object is null, filtering will be skipped"); + return null; + } MethodSecurityExpressionHandler expressionHandler = this.registry.getExpressionHandler(); EvaluationContext ctx = expressionHandler.createEvaluationContext(this::getAuthentication, mi); return expressionHandler.filter(returnedObject, attribute.getExpression(), ctx); diff --git a/core/src/test/java/org/springframework/security/authorization/method/PostFilterAuthorizationMethodInterceptorTests.java b/core/src/test/java/org/springframework/security/authorization/method/PostFilterAuthorizationMethodInterceptorTests.java index 31fee409f95..12710673fc7 100644 --- a/core/src/test/java/org/springframework/security/authorization/method/PostFilterAuthorizationMethodInterceptorTests.java +++ b/core/src/test/java/org/springframework/security/authorization/method/PostFilterAuthorizationMethodInterceptorTests.java @@ -109,6 +109,20 @@ public Object proceed() { assertThat(result).asInstanceOf(InstanceOfAssertFactories.array(String[].class)).containsOnly("john"); } + // gh-19280 + @Test + public void invokeWhenReturnedObjectIsNullThenSkipsFilteringAndReturnsNull() throws Throwable { + MockMethodInvocation methodInvocation = new MockMethodInvocation(new TestClass(), TestClass.class, + "doSomethingArray", new Class[] { String[].class }, new Object[] { null }) { + @Override + public Object proceed() { + return null; + } + }; + PostFilterAuthorizationMethodInterceptor advice = new PostFilterAuthorizationMethodInterceptor(); + assertThat(advice.invoke(methodInvocation)).isNull(); + } + @Test public void checkInheritedAnnotationsWhenConflictingThenAnnotationConfigurationException() throws Exception { MockMethodInvocation methodInvocation = new MockMethodInvocation(new ConflictingAnnotations(),