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); } /**
