This is an automated email from the ASF dual-hosted git repository. kusal pushed a commit to branch WW-5439-fix-dev-mode in repository https://gitbox.apache.org/repos/asf/struts.git
commit 6e07b01b65e5067c311ad5eed24e5a1f0524850d Author: Kusal Kithul-Godage <g...@kusal.io> AuthorDate: Mon Jul 8 18:42:06 2024 +1000 WW-5439 Move Dev Mode security configuration --- .../com/opensymphony/xwork2/ognl/OgnlUtil.java | 54 +++++++++++----------- .../xwork2/ognl/SecurityMemberAccess.java | 50 ++++++++++++++++++++ 2 files changed, 76 insertions(+), 28 deletions(-) diff --git a/core/src/main/java/com/opensymphony/xwork2/ognl/OgnlUtil.java b/core/src/main/java/com/opensymphony/xwork2/ognl/OgnlUtil.java index 681aac57d..1fee7a257 100644 --- a/core/src/main/java/com/opensymphony/xwork2/ognl/OgnlUtil.java +++ b/core/src/main/java/com/opensymphony/xwork2/ognl/OgnlUtil.java @@ -47,7 +47,6 @@ import java.util.Collection; import java.util.HashMap; import java.util.Map; import java.util.Set; -import java.util.concurrent.atomic.AtomicBoolean; import java.util.regex.Pattern; import static com.opensymphony.xwork2.util.ConfigParseUtil.toClassesSet; @@ -68,9 +67,6 @@ public class OgnlUtil { private static final Logger LOG = LogManager.getLogger(OgnlUtil.class); - // Flag used to reduce flooding logs with WARNs about using DevMode excluded packages - private final AtomicBoolean warnReported = new AtomicBoolean(false); - private final OgnlCache<String, Object> expressionCache; private final OgnlCache<Class<?>, BeanInfo> beanInfoCache; private TypeConverter defaultConverter; @@ -80,11 +76,6 @@ public class OgnlUtil { private boolean enableExpressionCache = true; private boolean enableEvalExpression; - private String devModeExcludedClasses = ""; - private String devModeExcludedPackageNamePatterns = ""; - private String devModeExcludedPackageNames = ""; - private String devModeExcludedPackageExemptClasses = ""; - private Container container; /** @@ -124,6 +115,7 @@ public class OgnlUtil { @Inject(StrutsConstants.STRUTS_DEVMODE) protected void setDevMode(String mode) { this.devMode = BooleanUtils.toBoolean(mode); + LOG.warn("Working in devMode, using devMode excluded classes and packages!"); } @Inject(value = StrutsConstants.STRUTS_OGNL_ENABLE_EXPRESSION_CACHE, required = false) @@ -164,9 +156,12 @@ public class OgnlUtil { // Must be set directly on SecurityMemberAccess } - @Inject(value = StrutsConstants.STRUTS_DEV_MODE_EXCLUDED_CLASSES, required = false) + /** + * @deprecated since 6.5.0, no replacement. + */ + @Deprecated protected void setDevModeExcludedClasses(String commaDelimitedClasses) { - this.devModeExcludedClasses = commaDelimitedClasses; + // Must be set directly on SecurityMemberAccess } /** @@ -177,9 +172,12 @@ public class OgnlUtil { // Must be set directly on SecurityMemberAccess } - @Inject(value = StrutsConstants.STRUTS_DEV_MODE_EXCLUDED_PACKAGE_NAME_PATTERNS, required = false) + /** + * @deprecated since 6.5.0, no replacement. + */ + @Deprecated protected void setDevModeExcludedPackageNamePatterns(String commaDelimitedPackagePatterns) { - this.devModeExcludedPackageNamePatterns = commaDelimitedPackagePatterns; + // Must be set directly on SecurityMemberAccess } /** @@ -190,9 +188,12 @@ public class OgnlUtil { // Must be set directly on SecurityMemberAccess } - @Inject(value = StrutsConstants.STRUTS_DEV_MODE_EXCLUDED_PACKAGE_NAMES, required = false) + /** + * @deprecated since 6.5.0, no replacement. + */ + @Deprecated protected void setDevModeExcludedPackageNames(String commaDelimitedPackageNames) { - this.devModeExcludedPackageNames = commaDelimitedPackageNames; + // Must be set directly on SecurityMemberAccess } /** @@ -203,9 +204,12 @@ public class OgnlUtil { // Must be set directly on SecurityMemberAccess } - @Inject(value = StrutsConstants.STRUTS_DEV_MODE_EXCLUDED_PACKAGE_EXEMPT_CLASSES, required = false) + /** + * @deprecated since 6.5.0, no replacement. + */ + @Deprecated public void setDevModeExcludedPackageExemptClasses(String commaDelimitedClasses) { - this.devModeExcludedPackageExemptClasses = commaDelimitedClasses; + // Must be set directly on SecurityMemberAccess } /** @@ -856,6 +860,11 @@ public class OgnlUtil { return createDefaultContext(root, null); } + /** + * Note that the allowlist capability is not enforced by the {@link OgnlContext} returned by this method. Currently, + * this context is only leveraged by some public methods on {@link OgnlUtil} which are called by + * {@link OgnlReflectionProvider}. + */ protected Map<String, Object> createDefaultContext(Object root, ClassResolver resolver) { if (resolver == null) { resolver = container.getInstance(RootAccessor.class); @@ -867,17 +876,6 @@ public class OgnlUtil { SecurityMemberAccess memberAccess = container.getInstance(SecurityMemberAccess.class); memberAccess.useEnforceAllowlistEnabled(Boolean.FALSE.toString()); - if (devMode) { - if (!warnReported.get()) { - warnReported.set(true); - LOG.warn("Working in devMode, using devMode excluded classes and packages!"); - } - memberAccess.useExcludedClasses(devModeExcludedClasses); - memberAccess.useExcludedPackageNamePatterns(devModeExcludedPackageNamePatterns); - memberAccess.useExcludedPackageNames(devModeExcludedPackageNames); - memberAccess.useExcludedPackageExemptClasses(devModeExcludedPackageExemptClasses); - } - return Ognl.createDefaultContext(root, memberAccess, resolver, defaultConverter); } diff --git a/core/src/main/java/com/opensymphony/xwork2/ognl/SecurityMemberAccess.java b/core/src/main/java/com/opensymphony/xwork2/ognl/SecurityMemberAccess.java index f882b2c58..f2eab0c3e 100644 --- a/core/src/main/java/com/opensymphony/xwork2/ognl/SecurityMemberAccess.java +++ b/core/src/main/java/com/opensymphony/xwork2/ognl/SecurityMemberAccess.java @@ -77,16 +77,27 @@ public class SecurityMemberAccess implements MemberAccess { private final ProviderAllowlist providerAllowlist; private final ThreadAllowlist threadAllowlist; + private boolean allowStaticFieldAccess = true; + private Set<Pattern> excludeProperties = emptySet(); private Set<Pattern> acceptProperties = emptySet(); + private Set<String> excludedClasses = unmodifiableSet(new HashSet<>(singletonList(Object.class.getName()))); private Set<Pattern> excludedPackageNamePatterns = emptySet(); private Set<String> excludedPackageNames = emptySet(); private Set<String> excludedPackageExemptClasses = emptySet(); + + private boolean devMode; + private Set<String> devModeExcludedClasses = unmodifiableSet(new HashSet<>(singletonList(Object.class.getName()))); + private Set<Pattern> devModeExcludedPackageNamePatterns = emptySet(); + private Set<String> devModeExcludedPackageNames = emptySet(); + private Set<String> devModeExcludedPackageExemptClasses = emptySet(); + private boolean enforceAllowlistEnabled = false; private Set<Class<?>> allowlistClasses = emptySet(); private Set<String> allowlistPackageNames = emptySet(); + private boolean disallowProxyObjectAccess = false; private boolean disallowProxyMemberAccess = false; private boolean disallowDefaultPackageAccess = false; @@ -460,4 +471,43 @@ public class SecurityMemberAccess implements MemberAccess { public void useDisallowDefaultPackageAccess(String disallowDefaultPackageAccess) { this.disallowDefaultPackageAccess = BooleanUtils.toBoolean(disallowDefaultPackageAccess); } + + @Inject(StrutsConstants.STRUTS_DEVMODE) + protected void setDevMode(String devMode) { + this.devMode = BooleanUtils.toBoolean(devMode); + setDevModeConfiguration(); + } + + @Inject(value = StrutsConstants.STRUTS_DEV_MODE_EXCLUDED_CLASSES, required = false) + public void useDevModeExcludedClasses(String commaDelimitedClasses) { + this.devModeExcludedClasses = toNewClassesSet(devModeExcludedClasses, commaDelimitedClasses); + setDevModeConfiguration(); + } + + @Inject(value = StrutsConstants.STRUTS_DEV_MODE_EXCLUDED_PACKAGE_NAME_PATTERNS, required = false) + public void useDevModeExcludedPackageNamePatterns(String commaDelimitedPackagePatterns) { + this.devModeExcludedPackageNamePatterns = toNewPatternsSet(devModeExcludedPackageNamePatterns, commaDelimitedPackagePatterns); + setDevModeConfiguration(); + } + + @Inject(value = StrutsConstants.STRUTS_DEV_MODE_EXCLUDED_PACKAGE_NAMES, required = false) + public void useDevModeExcludedPackageNames(String commaDelimitedPackageNames) { + this.devModeExcludedPackageNames = toNewPackageNamesSet(devModeExcludedPackageNames, commaDelimitedPackageNames); + setDevModeConfiguration(); + } + + @Inject(value = StrutsConstants.STRUTS_DEV_MODE_EXCLUDED_PACKAGE_EXEMPT_CLASSES, required = false) + public void useDevModeExcludedPackageExemptClasses(String commaDelimitedClasses) { + this.devModeExcludedPackageExemptClasses = toClassesSet(commaDelimitedClasses); + setDevModeConfiguration(); + } + + private void setDevModeConfiguration() { + if (this.devMode) { + excludedClasses = devModeExcludedClasses; + excludedPackageNamePatterns = devModeExcludedPackageNamePatterns; + excludedPackageNames = devModeExcludedPackageNames; + excludedPackageExemptClasses = devModeExcludedPackageExemptClasses; + } + } }