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

lukaszlenart pushed a commit to branch WW-4858-json-parameter-filtering
in repository https://gitbox.apache.org/repos/asf/struts.git

commit c4335c68d2cf5c05282200c47ed744df83ea3609
Author: Lukasz Lenart <[email protected]>
AuthorDate: Wed Jul 8 20:58:25 2026 +0200

    WW-4858 test(json): cover nested and list-element paths; clarify filter 
comments
    
    Co-Authored-By: Claude Opus 4.8 <[email protected]>
---
 .../org/apache/struts2/json/JSONInterceptor.java   |  3 +-
 .../apache/struts2/json/JSONInterceptorTest.java   | 39 ++++++++++++++++++++++
 2 files changed, 41 insertions(+), 1 deletion(-)

diff --git 
a/plugins/json/src/main/java/org/apache/struts2/json/JSONInterceptor.java 
b/plugins/json/src/main/java/org/apache/struts2/json/JSONInterceptor.java
index 0d584d830..b1c172388 100644
--- a/plugins/json/src/main/java/org/apache/struts2/json/JSONInterceptor.java
+++ b/plugins/json/src/main/java/org/apache/struts2/json/JSONInterceptor.java
@@ -144,7 +144,7 @@ public class JSONInterceptor extends AbstractInterceptor {
                 if (rootObject == null) // model overrides action
                     rootObject = invocation.getStack().peek();
 
-                // enforce @StrutsParameter authorization on JSON body keys
+                // enforce name/value acceptability (patterns, length, *Aware) 
and @StrutsParameter authorization on JSON body keys
                 filterUnacceptableKeys(json, rootObject, 
invocation.getAction());
 
                 // populate fields
@@ -263,6 +263,7 @@ public class JSONInterceptor extends AbstractInterceptor {
                 filterUnacceptableKeysRecursive((Map) item, elementPrefix, 
target, action);
             } else if (item instanceof java.util.List) {
                 filterUnacceptableList((java.util.List) item, elementPrefix, 
target, action);
+            // Scalar list elements are value-checked only; their parent key 
already passed name/authorization checks.
             } else if (!isAcceptableValue(elementPrefix, item, action)) {
                 it.remove();
             }
diff --git 
a/plugins/json/src/test/java/org/apache/struts2/json/JSONInterceptorTest.java 
b/plugins/json/src/test/java/org/apache/struts2/json/JSONInterceptorTest.java
index 89ec91dfb..e1aed361b 100644
--- 
a/plugins/json/src/test/java/org/apache/struts2/json/JSONInterceptorTest.java
+++ 
b/plugins/json/src/test/java/org/apache/struts2/json/JSONInterceptorTest.java
@@ -749,6 +749,45 @@ public class JSONInterceptorTest extends StrutsTestCase {
         assertNull(action.getBar());
     }
 
+    public void testExcludedNamePatternRejectsNestedKey() throws Exception {
+        this.request.setContent("{\"bean\": {\"stringField\": \"keep\", 
\"intField\": 42}}".getBytes());
+        this.request.addHeader("Content-Type", "application/json");
+
+        JSONInterceptor interceptor = createInterceptor();
+        org.apache.struts2.security.DefaultExcludedPatternsChecker excluded =
+                new 
org.apache.struts2.security.DefaultExcludedPatternsChecker();
+        excluded.setExcludedPatterns("bean\\.intField");
+        interceptor.setExcludedPatterns(excluded);
+        TestAction action = new TestAction();
+
+        this.invocation.setAction(action);
+        this.invocation.getStack().push(action);
+
+        interceptor.intercept(this.invocation);
+
+        assertNotNull(action.getBean());
+        assertEquals("keep", action.getBean().getStringField());
+        assertEquals(0, action.getBean().getIntField());
+    }
+
+    public void testExcludedValuePatternRejectsListElement() throws Exception {
+        this.request.setContent("{\"list\": [\"good\", 
\"badvalue\"]}".getBytes());
+        this.request.addHeader("Content-Type", "application/json");
+
+        JSONInterceptor interceptor = createInterceptor();
+        interceptor.setExcludedValuePatterns("badvalue");
+        TestAction action = new TestAction();
+
+        this.invocation.setAction(action);
+        this.invocation.getStack().push(action);
+
+        interceptor.intercept(this.invocation);
+
+        assertNotNull(action.getList());
+        assertEquals(1, action.getList().size());
+        assertEquals("good", action.getList().get(0));
+    }
+
     public void testParamNameMaxLengthRejectsLongKey() throws Exception {
         this.request.setContent("{\"foo\":\"a\"}".getBytes());
         this.request.addHeader("Content-Type", "application/json");

Reply via email to