[ https://issues.apache.org/jira/browse/WW-5364?focusedWorklogId=893745&page=com.atlassian.jira.plugin.system.issuetabpanels:worklog-tabpanel#worklog-893745 ]
ASF GitHub Bot logged work on WW-5364: -------------------------------------- Author: ASF GitHub Bot Created on: 04/Dec/23 11:44 Start Date: 04/Dec/23 11:44 Worklog Time Spent: 10m Work Description: kusalk commented on code in PR #800: URL: https://github.com/apache/struts/pull/800#discussion_r1413740321 ########## core/src/main/java/com/opensymphony/xwork2/XWorkJUnit4TestCase.java: ########## Review Comment: Moved this here so that we can utilise it for tests in core ########## apps/showcase/src/main/resources/struts.xml: ########## @@ -34,6 +34,19 @@ <constant name="struts.custom.i18n.resources" value="globalMessages" /> <constant name="struts.action.extension" value="action,," /> + <constant name="struts.allowlist.enable" value="true" /> Review Comment: It works! ########## core/src/main/java/com/opensymphony/xwork2/ognl/SecurityMemberAccess.java: ########## @@ -65,12 +80,14 @@ public class SecurityMemberAccess implements MemberAccess { private Set<String> excludedPackageNames = emptySet(); private Set<String> excludedPackageExemptClasses = emptySet(); private boolean enforceAllowlistEnabled = false; - private Set<String> allowlistClasses = emptySet(); + private Set<Class<?>> allowlistClasses = emptySet(); Review Comment: While we use `String` comparison for the exclusion list, we use `Class` comparison for the allowlist to prevent accidentally allowing through another Class with the same name (in applications with multiple classloaders) ########## core/src/main/resources/struts-beans.xml: ########## @@ -169,6 +169,7 @@ <bean name="struts" class="com.opensymphony.xwork2.ognl.SecurityMemberAccess" scope="prototype"/> <bean type="org.apache.struts2.ognl.OgnlGuard" name="struts" class="org.apache.struts2.ognl.StrutsOgnlGuard"/> + <bean class="org.apache.struts2.ognl.ProviderAllowlist"/> Review Comment: No extension point - can't see any use for one ########## plugins/junit/src/main/java/org/apache/struts2/junit/XWorkJUnit4TestCase.java: ########## @@ -18,74 +18,5 @@ */ package org.apache.struts2.junit; -import com.opensymphony.xwork2.ActionProxyFactory; -import com.opensymphony.xwork2.config.Configuration; -import com.opensymphony.xwork2.config.ConfigurationException; -import com.opensymphony.xwork2.config.ConfigurationManager; -import com.opensymphony.xwork2.config.ConfigurationProvider; -import com.opensymphony.xwork2.inject.Container; -import com.opensymphony.xwork2.inject.ContainerBuilder; -import com.opensymphony.xwork2.inject.Context; -import com.opensymphony.xwork2.inject.Factory; -import com.opensymphony.xwork2.inject.Scope; -import com.opensymphony.xwork2.test.StubConfigurationProvider; -import com.opensymphony.xwork2.util.XWorkTestCaseHelper; -import com.opensymphony.xwork2.util.location.LocatableProperties; -import org.junit.After; -import org.junit.Before; - -public abstract class XWorkJUnit4TestCase { - - protected ConfigurationManager configurationManager; - protected Configuration configuration; - protected Container container; - protected ActionProxyFactory actionProxyFactory; - - @Before - public void setUp() throws Exception { - configurationManager = XWorkTestCaseHelper.setUp(); - configuration = configurationManager.getConfiguration(); - container = configuration.getContainer(); - actionProxyFactory = container.getInstance(ActionProxyFactory.class); - } - - @After - public void tearDown() throws Exception { - XWorkTestCaseHelper.tearDown(configurationManager); - configurationManager = null; - configuration = null; - container = null; - actionProxyFactory = null; - } - - protected void loadConfigurationProviders(ConfigurationProvider... providers) { - configurationManager = XWorkTestCaseHelper.loadConfigurationProviders(configurationManager, providers); - configuration = configurationManager.getConfiguration(); - container = configuration.getContainer(); - actionProxyFactory = container.getInstance(ActionProxyFactory.class); - } - - protected void loadButAdd(final Class<?> type, final Object impl) { - loadButAdd(type, Container.DEFAULT_NAME, impl); - } - - protected void loadButAdd(final Class<?> type, final String name, final Object impl) { - loadConfigurationProviders(new StubConfigurationProvider() { - @Override - public void register(ContainerBuilder builder, - LocatableProperties props) throws ConfigurationException { - builder.factory(type, name, new Factory() { - public Object create(Context context) throws Exception { - return impl; - } - - @Override - public Class type() { - return impl.getClass(); - } - }, Scope.SINGLETON); - } - }); - } - +public abstract class XWorkJUnit4TestCase extends com.opensymphony.xwork2.XWorkJUnit4TestCase { Review Comment: Extended the moved class for compat ########## core/src/main/resources/struts-default.xml: ########## @@ -44,8 +44,6 @@ <interceptors> <interceptor name="alias" class="com.opensymphony.xwork2.interceptor.AliasInterceptor"/> - <interceptor name="autowiring" Review Comment: This class isn't provided by core ########## plugins/junit/src/main/java/org/apache/struts2/junit/XWorkTestCase.java: ########## @@ -0,0 +1,22 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.struts2.junit; + +public abstract class XWorkTestCase extends com.opensymphony.xwork2.XWorkTestCase { Review Comment: Added this for consistency ########## core/src/main/java/com/opensymphony/xwork2/config/providers/XmlDocConfigurationProvider.java: ########## Review Comment: Made some changes to this file to attempt to load every class defined in a `package` and add it to the allowlist ########## core/src/main/java/com/opensymphony/xwork2/config/impl/DefaultConfiguration.java: ########## @@ -395,6 +359,57 @@ protected Container createBootstrapContainer(List<ContainerProvider> providers) return builder.create(true); } + public static ContainerBuilder bootstrapFactories(ContainerBuilder builder) { Review Comment: Extracted code into this method for reuse by the `StrutsDefaultConfigurationProvider` ########## core/src/main/java/com/opensymphony/xwork2/ognl/SecurityMemberAccess.java: ########## @@ -57,6 +59,19 @@ public class SecurityMemberAccess implements MemberAccess { private static final Logger LOG = LogManager.getLogger(SecurityMemberAccess.class); + private static final Set<String> ALLOWLIST_REQUIRED_PACKAGES = unmodifiableSet(new HashSet<>(Arrays.asList( Review Comment: Required system allowlist defined here - it's possible I've missed some packages/classes, can add as needed ########## core/src/test/java/com/opensymphony/xwork2/config/providers/ConfigurationProviderOgnlAllowlistTest.java: ########## @@ -0,0 +1,114 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package com.opensymphony.xwork2.config.providers; + +import com.opensymphony.xwork2.XWorkJUnit4TestCase; +import com.opensymphony.xwork2.config.ConfigurationProvider; +import org.apache.struts2.config.StrutsXmlConfigurationProvider; +import org.apache.struts2.ognl.ProviderAllowlist; +import org.junit.Before; +import org.junit.Test; + +import static org.assertj.core.api.Assertions.assertThat; + +public class ConfigurationProviderOgnlAllowlistTest extends XWorkJUnit4TestCase { + + private final ConfigurationProvider testXml1 = new StrutsXmlConfigurationProvider("com/opensymphony/xwork2/config/providers/xwork-test-allowlist.xml"); + private final ConfigurationProvider testXml2 = new StrutsXmlConfigurationProvider("com/opensymphony/xwork2/config/providers/xwork-test-allowlist-2.xml"); + private ProviderAllowlist providerAllowlist; + + @Before + public void setUp() throws Exception { + loadConfigurationProviders(testXml1, testXml2); + providerAllowlist = container.getInstance(ProviderAllowlist.class); + } + + @Test + public void allowlist() throws Exception { + loadConfigurationProviders(testXml1, testXml2); + providerAllowlist = container.getInstance(ProviderAllowlist.class); + + assertThat(providerAllowlist.getProviderAllowlist()).containsExactlyInAnyOrder( + Class.forName("com.opensymphony.xwork2.interceptor.ValidationAware"), + Class.forName("com.opensymphony.xwork2.LocaleProvider"), + Class.forName("java.io.Serializable"), + Class.forName("com.opensymphony.xwork2.mock.MockResult"), + Class.forName("com.opensymphony.xwork2.interceptor.ConditionalInterceptor"), + Class.forName("com.opensymphony.xwork2.ActionSupport"), + Class.forName("com.opensymphony.xwork2.ActionChainResult"), + Class.forName("com.opensymphony.xwork2.TextProvider"), + Class.forName("org.apache.struts2.interceptor.NoOpInterceptor"), + Class.forName("com.opensymphony.xwork2.interceptor.Interceptor"), + Class.forName("java.lang.Object"), Review Comment: Even though `java.lang.Object` is added to the allowlist as it is a superclass, the exclusion list always takes precedence and so this class will not be allowed in practice Issue Time Tracking ------------------- Worklog Id: (was: 893745) Time Spent: 1h 40m (was: 1.5h) > Automatically populate OGNL allowlist > ------------------------------------- > > Key: WW-5364 > URL: https://issues.apache.org/jira/browse/WW-5364 > Project: Struts 2 > Issue Type: Improvement > Components: Core > Reporter: Kusal Kithul-Godage > Priority: Minor > Fix For: 6.4.0 > > Time Spent: 1h 40m > Remaining Estimate: 0h > -- This message was sent by Atlassian Jira (v8.20.10#820010)