This is an automated email from the ASF dual-hosted git repository.

lukaszlenart pushed a commit to branch WW-5627-cookie-authorization
in repository https://gitbox.apache.org/repos/asf/struts.git

commit 1cb44a7589a9c7add262df35d3e5fcd541d3573b
Author: Lukasz Lenart <[email protected]>
AuthorDate: Sat May 9 18:52:31 2026 +0200

    WW-5627 delegate ParametersInterceptor OGNL allowlisting to 
OgnlParameterAllowlister
    
    Also register ParameterAllowlister in DefaultConfiguration bootstrap
    factories so it is available in test containers (parallel to how
    ParameterAuthorizer was already registered there).
    
    Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
---
 .../struts2/config/impl/DefaultConfiguration.java  |  3 ++
 .../parameter/ParametersInterceptor.java           | 43 ++++------------------
 2 files changed, 10 insertions(+), 36 deletions(-)

diff --git 
a/core/src/main/java/org/apache/struts2/config/impl/DefaultConfiguration.java 
b/core/src/main/java/org/apache/struts2/config/impl/DefaultConfiguration.java
index 9eb009592..dcf4f1602 100644
--- 
a/core/src/main/java/org/apache/struts2/config/impl/DefaultConfiguration.java
+++ 
b/core/src/main/java/org/apache/struts2/config/impl/DefaultConfiguration.java
@@ -92,6 +92,8 @@ import org.apache.struts2.ognl.SecurityMemberAccess;
 import org.apache.struts2.ognl.accessor.CompoundRootAccessor;
 import org.apache.struts2.ognl.accessor.RootAccessor;
 import org.apache.struts2.ognl.accessor.XWorkMethodAccessor;
+import org.apache.struts2.interceptor.parameter.OgnlParameterAllowlister;
+import org.apache.struts2.interceptor.parameter.ParameterAllowlister;
 import org.apache.struts2.interceptor.parameter.StrutsParameterAuthorizer;
 import org.apache.struts2.interceptor.parameter.ParameterAuthorizer;
 import org.apache.struts2.util.StrutsProxyService;
@@ -409,6 +411,7 @@ public class DefaultConfiguration implements Configuration {
                 .factory(ProxyCacheFactory.class, 
StrutsProxyCacheFactory.class, Scope.SINGLETON)
                 .factory(ProxyService.class, StrutsProxyService.class, 
Scope.SINGLETON)
                 .factory(ParameterAuthorizer.class, 
StrutsParameterAuthorizer.class, Scope.SINGLETON)
+                .factory(ParameterAllowlister.class, 
OgnlParameterAllowlister.class, Scope.SINGLETON)
                 .factory(OgnlUtil.class, Scope.SINGLETON)
                 .factory(SecurityMemberAccess.class, Scope.PROTOTYPE)
                 .factory(OgnlGuard.class, StrutsOgnlGuard.class, 
Scope.SINGLETON)
diff --git 
a/core/src/main/java/org/apache/struts2/interceptor/parameter/ParametersInterceptor.java
 
b/core/src/main/java/org/apache/struts2/interceptor/parameter/ParametersInterceptor.java
index 5491b585f..6b7df1ff8 100644
--- 
a/core/src/main/java/org/apache/struts2/interceptor/parameter/ParametersInterceptor.java
+++ 
b/core/src/main/java/org/apache/struts2/interceptor/parameter/ParametersInterceptor.java
@@ -65,10 +65,8 @@ import java.util.regex.Pattern;
 import static java.lang.String.format;
 import static java.util.Collections.unmodifiableSet;
 import static java.util.stream.Collectors.joining;
-import static org.apache.commons.lang3.StringUtils.indexOfAny;
 import static org.apache.commons.lang3.StringUtils.normalizeSpace;
 import static 
org.apache.struts2.security.DefaultAcceptedPatternsChecker.NESTING_CHARS;
-import static 
org.apache.struts2.security.DefaultAcceptedPatternsChecker.NESTING_CHARS_STR;
 import static org.apache.struts2.util.DebugUtils.logWarningForFirstOccurrence;
 import static org.apache.struts2.util.DebugUtils.notifyDeveloperOfError;
 
@@ -100,6 +98,7 @@ public class ParametersInterceptor extends 
MethodFilterInterceptor {
     private Set<Pattern> excludedValuePatterns = null;
     private Set<Pattern> acceptedValuePatterns = null;
     private ParameterAuthorizer parameterAuthorizer;
+    private ParameterAllowlister parameterAllowlister;
 
     @Inject
     public void setValueStackFactory(ValueStackFactory valueStackFactory) {
@@ -126,6 +125,11 @@ public class ParametersInterceptor extends 
MethodFilterInterceptor {
         this.parameterAuthorizer = parameterAuthorizer;
     }
 
+    @Inject
+    public void setParameterAllowlister(ParameterAllowlister 
parameterAllowlister) {
+        this.parameterAllowlister = parameterAllowlister;
+    }
+
     @Inject(StrutsConstants.STRUTS_DEVMODE)
     public void setDevMode(String mode) {
         this.devMode = BooleanUtils.toBoolean(mode);
@@ -388,40 +392,7 @@ public class ParametersInterceptor extends 
MethodFilterInterceptor {
      * injection and must NOT be shared with other input channels (JSON, REST).
      */
     private void performOgnlAllowlisting(String name, Object target, long 
paramDepth) {
-        int nestingIndex = indexOfAny(name, NESTING_CHARS_STR);
-        String rootProperty = nestingIndex == -1 ? name : name.substring(0, 
nestingIndex);
-        String normalisedRootProperty = 
Character.toLowerCase(rootProperty.charAt(0)) + rootProperty.substring(1);
-
-        BeanInfo beanInfo = getBeanInfo(target);
-        if (beanInfo != null) {
-            Optional<PropertyDescriptor> propDescOpt = 
Arrays.stream(beanInfo.getPropertyDescriptors())
-                    .filter(desc -> 
desc.getName().equals(normalisedRootProperty)).findFirst();
-            if (propDescOpt.isPresent()) {
-                PropertyDescriptor propDesc = propDescOpt.get();
-                Method relevantMethod = paramDepth == 0 ? 
propDesc.getWriteMethod() : propDesc.getReadMethod();
-                if (relevantMethod != null && 
getPermittedInjectionDepth(relevantMethod) >= paramDepth) {
-                    allowlistClass(propDesc.getPropertyType());
-                    if (paramDepth >= 2) {
-                        allowlistReturnTypeIfParameterized(relevantMethod);
-                    }
-                    return;
-                }
-            }
-        }
-
-        // Fallback: check public field
-        Class<?> targetClass = ultimateClass(target);
-        try {
-            Field field = targetClass.getDeclaredField(normalisedRootProperty);
-            if (Modifier.isPublic(field.getModifiers()) && 
getPermittedInjectionDepth(field) >= paramDepth) {
-                allowlistClass(field.getType());
-                if (paramDepth >= 2) {
-                    allowlistFieldIfParameterized(field);
-                }
-            }
-        } catch (NoSuchFieldException e) {
-            // No field to allowlist
-        }
+        parameterAllowlister.allowlistAuthorizedPath(name, target);
     }
 
     /**

Reply via email to