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

lukaszlenart pushed a commit to branch WW-5675-share-parsed-ognl-security-config
in repository https://gitbox.apache.org/repos/asf/struts.git

commit cb3dff2ff2df3e375dbb2832de88f0d5be0ded61
Author: Lukasz Lenart <[email protected]>
AuthorDate: Fri Aug 14 14:40:01 2026 +0200

    WW-5675 refactor(ognl): drop the lazy dev-mode flip from the access path
    
    Co-Authored-By: Claude Opus 5 <[email protected]>
---
 .../apache/struts2/ognl/SecurityMemberAccess.java  | 45 ----------------------
 .../SecurityMemberAccessConfigSharingTest.java     | 25 ++++++++++++
 2 files changed, 25 insertions(+), 45 deletions(-)

diff --git 
a/core/src/main/java/org/apache/struts2/ognl/SecurityMemberAccess.java 
b/core/src/main/java/org/apache/struts2/ognl/SecurityMemberAccess.java
index 8ba19f540..b7ed69caa 100644
--- a/core/src/main/java/org/apache/struts2/ognl/SecurityMemberAccess.java
+++ b/core/src/main/java/org/apache/struts2/ognl/SecurityMemberAccess.java
@@ -86,13 +86,6 @@ public class SecurityMemberAccess implements MemberAccess {
     private Set<String> excludedPackageNames = emptySet();
     private Set<String> excludedPackageExemptClasses = emptySet();
 
-    private volatile boolean isDevModeInit;
-    private boolean isDevMode;
-    private Set<String> devModeExcludedClasses = 
Set.of(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();
@@ -283,7 +276,6 @@ public class SecurityMemberAccess implements MemberAccess {
      * @return {@code true} if member access is allowed
      */
     protected boolean checkExclusionList(Object target, Member member) {
-        useDevModeConfiguration();
         Class<?> memberClass = member.getDeclaringClass();
         if (isClassExcluded(memberClass)) {
             LOG.warn("Declaring class of member type [{}] is excluded!", 
memberClass);
@@ -612,41 +604,4 @@ public class SecurityMemberAccess implements MemberAccess {
         this.disallowDefaultPackageAccess = 
BooleanUtils.toBoolean(disallowDefaultPackageAccess);
     }
 
-    @Inject(StrutsConstants.STRUTS_DEVMODE)
-    protected void useDevMode(String devMode) {
-        this.isDevMode = BooleanUtils.toBoolean(devMode);
-    }
-
-    @Inject(value = StrutsConstants.STRUTS_DEV_MODE_EXCLUDED_CLASSES, required 
= false)
-    public void useDevModeExcludedClasses(String commaDelimitedClasses) {
-        this.devModeExcludedClasses = toNewClassesSet(devModeExcludedClasses, 
commaDelimitedClasses);
-    }
-
-    @Inject(value = 
StrutsConstants.STRUTS_DEV_MODE_EXCLUDED_PACKAGE_NAME_PATTERNS, required = 
false)
-    public void useDevModeExcludedPackageNamePatterns(String 
commaDelimitedPackagePatterns) {
-        this.devModeExcludedPackageNamePatterns = 
toNewPatternsSet(devModeExcludedPackageNamePatterns, 
commaDelimitedPackagePatterns);
-    }
-
-    @Inject(value = StrutsConstants.STRUTS_DEV_MODE_EXCLUDED_PACKAGE_NAMES, 
required = false)
-    public void useDevModeExcludedPackageNames(String 
commaDelimitedPackageNames) {
-        this.devModeExcludedPackageNames = 
toNewPackageNamesSet(devModeExcludedPackageNames, commaDelimitedPackageNames);
-    }
-
-    @Inject(value = 
StrutsConstants.STRUTS_DEV_MODE_EXCLUDED_PACKAGE_EXEMPT_CLASSES, required = 
false)
-    public void useDevModeExcludedPackageExemptClasses(String 
commaDelimitedClasses) {
-        this.devModeExcludedPackageExemptClasses = 
toClassesSet(commaDelimitedClasses);
-    }
-
-    private void useDevModeConfiguration() {
-        if (!isDevMode || isDevModeInit) {
-            return;
-        }
-        logWarningForFirstOccurrence("devMode", LOG,
-                "DevMode enabled, using DevMode excluded classes and packages 
for OGNL security enforcement!");
-        isDevModeInit = true;
-        excludedClasses = devModeExcludedClasses;
-        excludedPackageNamePatterns = devModeExcludedPackageNamePatterns;
-        excludedPackageNames = devModeExcludedPackageNames;
-        excludedPackageExemptClasses = devModeExcludedPackageExemptClasses;
-    }
 }
diff --git 
a/core/src/test/java/org/apache/struts2/ognl/SecurityMemberAccessConfigSharingTest.java
 
b/core/src/test/java/org/apache/struts2/ognl/SecurityMemberAccessConfigSharingTest.java
index 5680e59fb..eb09c9fb4 100644
--- 
a/core/src/test/java/org/apache/struts2/ognl/SecurityMemberAccessConfigSharingTest.java
+++ 
b/core/src/test/java/org/apache/struts2/ognl/SecurityMemberAccessConfigSharingTest.java
@@ -148,4 +148,29 @@ public class SecurityMemberAccessConfigSharingTest extends 
XWorkTestCase {
             super(providerAllowlist, threadAllowlist);
         }
     }
+
+    /**
+     * Dev-mode exclusions must be in force from the first access, with no 
lazy flip.
+     */
+    public void testDevModeExclusionsApplyWithoutAnAccess() throws Exception {
+        loadButSet(Map.of(
+                StrutsConstants.STRUTS_DEVMODE, "true",
+                StrutsConstants.STRUTS_DEV_MODE_EXCLUDED_CLASSES, 
"java.lang.ProcessBuilder"));
+
+        SecurityMemberAccess sma = 
container.getInstance(SecurityMemberAccess.class);
+        Set<String> excluded = SecurityMemberAccessTest.reflectField(sma, 
"excludedClasses");
+
+        assertTrue("dev-mode exclusions were not applied at startup",
+                excluded.contains("java.lang.ProcessBuilder"));
+    }
+
+    public void testDevModeMethodsAreGone() throws Exception {
+        for (String name : new String[]{"useDevMode", 
"useDevModeExcludedClasses",
+                "useDevModeExcludedPackageNamePatterns", 
"useDevModeExcludedPackageNames",
+                "useDevModeExcludedPackageExemptClasses", 
"useDevModeConfiguration"}) {
+            for (java.lang.reflect.Method method : 
SecurityMemberAccess.class.getDeclaredMethods()) {
+                assertFalse("SecurityMemberAccess still declares " + name, 
method.getName().equals(name));
+            }
+        }
+    }
 }

Reply via email to